Swift协议要求,只能通过使用最终类来满足

我在Swift上为owner / ownee方案建模:
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

我正在试图理解这个错误的原因是什么,为什么让学生最终的类会修复它,如果有一些解决方法能够以不同的方式对其进行建模,而不会使这个类最终.我已经用Google搜索了这个错误,但到目前为止还没有找到太多.

错误是正确的.您必须使您的课程成为最终,因为没有子类可以符合您的协议Ownee.

考虑这个子类:

class FirstGradeStudent: Student {
   // inherited from parent
   // var owner: Owner<Student> {
   //     return professor
   //  }
}

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

解决方法

1:为Ownee定义一个超类,它应该由所有者使用:

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的类中,必须通过定义类型来将关联类型的抽象类型转换为具体类:

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

相关文章

软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘...
现实生活中,我们听到的声音都是时间连续的,我们称为这种信...
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿...
【Android App】实战项目之仿抖音的短视频分享App(附源码和...
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至...
因为我既对接过session、cookie,也对接过JWT,今年因为工作...