M.Shahzad Qamar
M.Shahzad Qamar

Reputation: 114

Best approach to make class design if we have two class as bellow :

Best approach to make class design if we have two class as below:

class Teacher {
    var name
    var age
    var TechId
}

class Student {
    var name
    var age
    var StdID
}

I try it using that :

class Person {
    var name
    var age
}

class Student : Person {
    var StdID
}

class Teacher : Person {
    var TechID
}

But now problem is that student become teacher and vice versa.

Can you any one provided best solutions for that using Swift?

Upvotes: 2

Views: 103

Answers (2)

Rob
Rob

Reputation: 437937

You said:

But now problem is that student become teacher and vice versa.

If you can change back and forth like this, I'd first suggest a concrete and distinct object to capture what precisely is transitioning from one to the other:

class Person {
    var name: String
    var age: Int
}

Note, in your example, you are considering this Person to be what other languages consider to be an abstract/virtual class. But I'm suggesting that you want to make this a concrete object (the actual person) that you instantiate.

The question then becomes how you represent "student" and "teacher". One simple pattern is to consider it a question of membership in some relevant collection:

typealias StudentID = String
var students: [StudentID: Person]

typealias TeacherID = String
var teachers: [TeacherID: Person]

In that case, transitioning from a student to a teacher (or vice versa) is merely a question of adding/removing from the appropriate dictionaries.

The above is a bit constrained, though. For example, what if you wanted to keep track of more student-specific properties (e.g. enrollment date, etc.) or teacher-specific properties (e.g. hire date, social security number, annual salary, etc.). This suggests you might want specific types for these student and teacher types:

class Student {
    let studentID: String
    let person: Person
}

class Teacher {
    let teacherID: String
    let person: Person
}

And then your students and teachers collections become simple arrays:

var students: [Student]
var teachers: [Teacher]

But by making the Person a property (rather than a base class), if you know which person is associated with a particular "student id", you can now associate that person with a particular "teacher id", too. But the idea is the same, it's merely a question of membership in the appropriate collection/type, not an issue of trying to change the inherent type of the person.


The alternative is a protocol oriented pattern:

protocol Person {
    var name: String { get }
    var age: Int { get }
}

struct Student: Person {
    let studentID: String
    var name: String
    var age: Int

    init(name: String, age: Int) {
        studentID = UUID().uuidString
        self.name = name
        self.age = age
    }

    init(person: Person) {
        self.init(name: person.name, age: person.age)
    }
}

struct Teacher: Person {
    let teacherID: String
    var name: String
    var age: Int

    init(name: String, age: Int) {
        teacherID = UUID().uuidString
        self.name = name
        self.age = age
    }

    init(person: Person) {
        self.init(name: person.name, age: person.age)
    }
}

This captures your notion that Person is an abstract type that simply conforms to having certain properties. It avoids any ambiguity that Person is not a type, itself, but merely a protocol to which types have to conform. You can only instantiate concrete Student and Teacher objects.

But then, if you want to create a Teacher from a Student, you can do:

let fred = Student(name: "Fred", age: 22)

let teacher = Teacher(person: fred)

Note, though, that this doesn’t “change” fred into a Teacher, but rather creates a new Teacher whose Person properties are copies of those of fred.

Upvotes: 2

totiDev
totiDev

Reputation: 5275

For Swift, I would recommend something like this:

protocol Person {
    var name: String { get }
    var age: Int { get }
}

struct Teacher: Person {
    let id: Int
    let name: String
    let age: Int
}

struct Student: Person {
    let id: Int
    let name: String
    let age: Int
}

Use a Protocol to define the person. And use a Struct for Teacher and Student because once created you would not change their details as a Struct is immutable. Both Teacher and Student conform to Person protocol.

To test if a person is a Teacher or Student, you could do this:

func test(person: Person) {
    switch person {
    case is Teacher:
        print("teacher")
    case is Student:
        print("student")
    default:
        preconditionFailure("Unknown person type")
    }
}

Upvotes: 2

Related Questions