我正在 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/