swift - 只能通过使用最终类来满足的 Swift 协议(protocol)要求

标签 swift oop generics swift-protocols

我正在 Swift 上为所有者/所有者方案建模:

class Owner<T: Ownee> {
     // ...
}

protocol Ownee {
    var owner: Owner<Self> { get }
}

然后我有一对遵循上述建模类型的教授/学生:

class Professor: Owner<Student> {
    // ...
}

class Student: Ownee {
    let professor: Professor
    var owner: Owner<Student> {  // error here (see below)
        return professor
    }

    init(professor: Professor) {
        self.professor = professor
    }
}

但是,在 Student 类中定义 var owner 时出现以下错误:

Protocol 'Ownee' requirement 'owner' cannot be satisfied by a non-final class ('Student') because it uses 'Self' in a non-parameter, non-result type position

我试图了解此错误的原因是什么,为什么将类 Student 设置为 final 会修复它,如果有一些解决方法能够以不同的方式对此进行建模,而无需创建此类最后。我已经用谷歌搜索了这个错误,但到目前为止还没有找到太多。

最佳答案

错误是正确的。你必须让你的类最终,因为没有子类可以符合你的协议(protocol) Ownee .

考虑这个子类:

class FirstGradeStudent: Student {
   // Student contains following variable:
   // var owner: Owner<Student> {
   //     return professor
   //  }
}

如您所见,它必须实现 var owner: Owner<Student>因为他的 parent ,但它应该实现 var owner: Owner<FirstGradeStudent>相反,因为协议(protocol)包含 var owner: Owner<Self> { get }在这种情况下 Self将是 FirstGradeStudent .

解决方法

1:定义一个父类(super class)到Ownee , 它应该被 Owner 使用:

class Owner<T: OwneeSuper> {
    // ...
}

protocol OwneeSuper {}    
protocol Ownee: OwneeSuper {
    associatedtype T: OwneeSuper
    var owner: Owner<T> { get }
}

OwneeSuper只是克服 this problem 的一种解决方法,否则我们只会使用:

protocol Ownee {
    associatedtype T: Ownee
    var owner: Owner<T> { get }
}

2. 在符合 Ownee 的类中, 你必须转 associatedtype 的抽象类型通过定义 typealias 进入具体类:

class Student: Ownee {
    typealias T = Student // <<-- define the property to be Owner<Student>
    let professor: Professor
    var owner: Owner<T> { 
        return professor
    }

    init(professor: Professor) {
        self.professor = professor
    }
}

3.子类现在可以使用该属性,该属性将属于您定义的类型:

class FirstGradeStudent: Student {
    func checkOwnerType() {
        if self.owner is Owner<Student> { //warning: 'is' test is always true
            print("yeah!")
        }
    }
}

关于swift - 只能通过使用最终类来满足的 Swift 协议(protocol)要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37141067/

相关文章:

ios - 尝试添加 UIImageView 数组的约束

swift - 惰性初始化变量持有函数 swift

php - 如果对象在同一类中实例化,则可以公开调用私有(private)函数

c# - SortedList<>、SortedDictionary<> 和 Dictionary<>

ios - 从 Objective-C 加载基于 Swift 的 UIViewController

json - Swift 解析 JSON、嵌套数组

c++ - 使用来自不同类的对象时出错

java - 如何知道我的手指在哪里、在哪个布局上?

c# - 在 C# 中使用泛型以避免代码重复

Java 推断类型化 HashSet 的类型错误