我在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 } }
但是我var owner在Student类中的定义上收到以下错误:
var owner
Student
非最终课程(“学生”)无法满足协议“ Ownee”的要求“所有者”,因为它在非参数,非结果类型的位置使用了“自我”
我试图了解导致此错误的原因,为什么将类定为Studentfinal可以解决该问题,以及是否存在一些解决方法能够以不同的方式对此模型进行建模而不将其定为final。我已经搜索过该错误,但到目前为止还没有发现太多。
错误是正确的。您必须将类定型,因为没有子类可以符合您的协议Ownee。
Ownee
考虑以下子类:
class FirstGradeStudent: Student { // inherited from parent // var owner: Owner<Student> { // return professor // } }
如您所见,var owner: Owner<Student>由于其父级,它必须实现,但是应该var owner: Owner<FirstGradeStudent>改为实现,因为协议包含var owner: Owner<Self> { get },在这种情况下Self为FirstGradeStudent。
var owner: Owner<Student>
var owner: Owner<FirstGradeStudent>
var owner: Owner<Self> { get }
Self
FirstGradeStudent
解决方法
1: 定义的超类Ownee,它应由Owner:
Owner
class Owner<T: OwneeSuper> { // ... } protocol OwneeSuper {} protocol Ownee: OwneeSuper { associatedtype T: OwneeSuper var owner: Owner<T> { get } }
OwneeSuper只是解决此问题的一种解决方法,否则我们将使用:
OwneeSuper
protocol Ownee { associatedtype T: Ownee var owner: Owner<T> { get } }
2. 在符合的类中Ownee,您必须associatedtype通过定义以下内容将的抽象类型转换为具体类typealias:
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!") } } }