如果我们有两个类如下,那么进行类设计的最佳方法是:

时间:2017-11-10 06:36:57

标签: swift oop design-patterns

如果我们有两个类如下,那么进行类设计的最佳方法是:

class Teacher {
    var name
    var age
    var TechId
}

class Student {
    var name
    var age
    var StdID
}

我尝试使用它:

class Person {
    var name
    var age
}

class Student : Person {
    var StdID
}

class Teacher : Person {
    var TechID
}

但现在问题是学生成为老师,反之亦然。

你能为使用Swift的人提供最佳解决方案吗?

2 个答案:

答案 0 :(得分:2)

对于Swift,我会推荐这样的东西:

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
}

使用协议定义此人。并使用Struct for Teacher和Student,因为一旦创建,您就不会更改其细节,因为Struct是不可变的。教师和学生都遵守人员协议。

要测试某人是教师还是学生,您可以这样做:

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

答案 1 :(得分:2)

你说:

  

但现在问题是学生成为老师,反之亦然。

如果你能像这样来回改变,我首先会建议一个具体而独特的物体来捕捉从一个到另一个的精确过渡:

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

注意,在您的示例中,您正在考虑将此Person视为其他语言认为是抽象/虚拟类的内容。但我建议你想让它成为你实例化的具体对象(实际的人)。

然后问题就变成了你代表“学生”和“老师”的方式。一个简单的模式是将其视为某些相关集合中的成员资格问题:

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

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

在这种情况下,从学生过渡到教师(反之亦然)仅仅是在适当的词典中添加/删除的问题。

但上述情况有点受限。例如,如果您想跟踪更多学生特定的属性(例如,注册日期等)或教师特定的属性(例如,雇用日期,社会安全号码,年薪等),该怎么办?这表明您可能需要这些学生和教师类型的特定类型:

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

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

然后你的学生和教师收藏成为简单的阵列:

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

但是通过使Person成为属性(而不是基类),如果您知道哪个人与特定的“学生ID”相关联,您现在可以将该人与特定的“教师ID”相关联也是。但这个想法是一样的,它只是一个适当的集合/类型的成员问题,而不是试图改变人的固有类型的问题。

替代方案是面向协议的模式:

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)
    }
}

这捕获了Person是一种简单地符合某些属性的抽象类型的概念。它避免了Person本身不是类型的任何歧义,而仅仅是类型必须符合的协议。您只能实例化具体的StudentTeacher对象。

但是,如果你想从Teacher创建一个Student,你可以这样做:

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

let teacher = Teacher(person: fred)

请注意,这不会将fred“更改”为Teacher,而是创建一个新的Teacher,其Person属性是fred属性的副本mutex mtx; void my_thread(vector<string> &V, int length) { string s=generate_some_string(length); //computationally intensive part mtx.lock(); V.push_back(s); mtx.unlock(); } int main() { vector<string> S; while(S.size()<1000) { vector<thread> ths; ths.resize(10); for(int i=0; i<10;i++) { ths[i]=thread(my_thread,ref(S),100 ); } for(auto &th: ths) th.join(); } }