0

I have an object that might look something like this...

class User {
    var username: String?
} 

I'd like to have users that could either be a student or a teacher. At the moment, I've added in properties to the User class like this...

class User {
    var username: String?
    // student properties
    var year: Int?
    // teacher properties
    var department: String?
} 

I'm sure I should be using inheritance here, but I'm worried that's going to make the control flow a bit complicated. For example, as part of the login function, I do this...

 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
 appDelegate.user = User(delegate: self)
 appDelegate.user!.load_from_user_defaults()

Or to get something from the current user, I would do this...

 let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
 var username = appDelegate.user.username

How would I use inheritance, in this situation, given that I wouldn't know if it was a teacher or a student logging in? Is it easier to stick to the way I'm doing it?

3
  • Since you have different attributes for student and teacher, I assume you must have a way of deciding which you're dealing with at some point. Commented Dec 4, 2015 at 13:15
  • 1
    Hint 1: don't ever use UIApplication.sharedApplication().delegate as! AppDelegate in your application but pass the reference to your value to the view controllers, starting from AppDelegate. Hint 2: Use the Factory Pattern - just google it. You can instantiate an instance of any of these classes via a static method of the superclass for example. Then you can access the username any time. Checking if someone is a Student: myVariable is Student. Accessing a variable of a student: (myVariable as? Student)?.year returns the year as optional (nil when it isn't a student, the value otherwise) Commented Dec 4, 2015 at 19:25
  • Thanks Oliver, I appreciate the advice. Looks like I've still got a lot of reading to do! When you say don't ever use the UIApp... line, is there a good reason not to? I'd like to understand why I'm writing something, rather than just what to change it to. I can see how you might do this using prepareForSegue e.g. link, but does that create a copy of object, or retain the original one? Commented Dec 5, 2015 at 20:29

2 Answers 2

1

Some options:

  • Super/Sub class pattern (inheritance) where you use downcast to check if it is a Student or a Teacher.

  • Protocols work the same as the Super/Sub pattern but a type can conform to many protocols but can only inherit from one super.

  • if both Student and Teacher have the same properties you can also just add a property (a bool or an enum) to determine which is which.

  • create an enum instead of a protocol or super class that has a rawValue of User and has cases for both Teacher and Student. (this is complicated)

  • Use an enum with associated values.

Every method has it's own benefits and drawbacks. If you want to be able to pass a User object to different functions in your app, you want to have some conformance/inheritance.


If you have some conformance/inheritance, you can load the user with a method of your choosing and then downcast as such:

if let student = user as? Student {
    // do student stuffs
} else if let teacher = user as? Teacher {
    // do teacher stuffs
}

Option 1, regular inheritance :

class User {
    var username: String?
}

class Student : User {
    // student properties
    var year: Int?
}

class Teacher : User {
    // teacher properties
    var department: String?
}

Option 2, conform to instead of inherit from, AKA Protcols :

protocol User : class {
    var username: String? { get set }
}

class Student : User {

    var username: String?
    // student properties
    var year: Int?
}

class Teacher : User {

    var username: String?
    // teacher properties
    var department: String?
}

Option 3, UserType property:

enum UserType {
    case Student
    case Teacher
}

class User {
    var username: String?
    // student properties, if it is a teacher we leave this blank
    var year: Int?
    // teacher properties,, if it is a student we leave this blank
    var department: String?

    var type : UserType?
}

Option 4, enum with User as rawValue:

class User: Equatable,StringLiteralConvertible {

    var username: String?
    // student properties
    var year: Int?
    // teacher properties
    var department: String?

    var type : String?

    init(withType type:String) {
        self.type = type
    }

    required convenience init(stringLiteral value: String) {

        self.init(withType: value)
    }

    required convenience init(extendedGraphemeClusterLiteral value: String) {
        self.init(withType: value)
    }

    required convenience init(unicodeScalarLiteral value: String) {
        self.init(withType: value)
    }
}

func ==(lhs:User,rhs:User) -> Bool {
    if lhs.username == rhs.username && lhs.department == rhs.department && lhs.year == rhs.year && lhs.type == rhs.type {
        return true
    } else {
        return false
    }
}


enum UserType : User {

    case Student = "Student"
    case Teacher = "Teacher"

}

let user = UserType.Teacher

Option 5, enum with associated values:

class User {

    var username: String?

}

class Student {
    // student properties
    var year: Int?
}

class Teacher {
    // teacher properties
    var department: String?
}


enum UserType {
    case student(Student)
    case teacher(Teacher)
}
Sign up to request clarification or add additional context in comments.

2 Comments

to be frank ......this is common in all OOP languages java--interfaces Swift--protocol C++, C#.......cool
haa...yes its smart enough to catch the point about inheritance in OOPs
0

"Could be either this or that": In Swift, you use an enumeration. One class for student, one class for teacher, one enumeration for "student or teacher".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.