我试图用一些AnyObject类型的属性来定义一个协议,然后在符合协议的类中,属性类型是SomeClass.但是这会返回编译器错误.我不得不将类中的类型更改为AnyObject.如何在协议定义中使用超类并将子类用作属性类型?
谢谢!
protocol TestProtocol {
var prop: [AnyObject] {get}
}
class Test: TestProtocol {
var prop = [SomeClass]() //compiler error
var prop = [AnyObject]() //this will work
}
Run Code Online (Sandbox Code Playgroud)
mat*_*att 10
数组是一个不必要的复杂,所以让我们删除它,只考虑一个简单的类型.这不合法:
protocol TestProtocol {
var prop: AnyObject {get}
}
class SomeClass {}
class Test: TestProtocol {
var prop : SomeClass = SomeClass() // error
}
Run Code Online (Sandbox Code Playgroud)
问题在于协议声明非常确切地说,声称采用TestProtocol的人必须具有prop AnyObject类型的属性 - 不是某种类型的属性,只是符合 AnyObject.
如果您发现这种情况令人惊讶,您可能会将类型实例与类型本身混淆.这是事实,一个实例 SomeClass的,可以使用其中一个实例 AnyObject的预期.但类型本身并不是这样的; 当协议要求AnyObject 类型时,不能替换SomeClass 类型.
要更清楚地看到这一点,请注意这确实编译得很好:
protocol TestProtocol {
var prop: AnyObject {get}
}
class SomeClass {}
class Test: TestProtocol {
var prop : AnyObject = SomeClass() // changing the declared _type_
}
Run Code Online (Sandbox Code Playgroud)
正如你已经发现的那样编译; 但是,正如你所说,这不是你想要的.那么如何做你想要的呢?
好吧,在Swift中,表达指定符合协议类型的类型的概念的方式是通过带约束的泛型.这就是你得到的答案.协议声明中的A 可以是制定通用协议的方式.并且泛型可以具有约束,例如,所讨论的类型应该符合协议或从类继承.因此,这是合法的,是您正在寻找的解决方案:typealias
protocol TestProtocol {
typealias T:AnyObject // generic
var prop: T {get}
}
class SomeClass {}
class Test: TestProtocol {
var prop : SomeClass = SomeClass() // :)
}
Run Code Online (Sandbox Code Playgroud)
该行typealias T:AnyObject说T必须是符合AnyObject的类型,这正是您想要说的.
您可以做的游乐场示例:
class SomeClass {
}
class Subclass : SomeClass{
}
protocol TestProtocol {
typealias T : SomeClass
var prop: [T] {get}
}
class Test: TestProtocol {
var prop = [Subclass]()
func test(){
prop.append(Subclass())
}
}
let test = Test()
test.test()
print(test.prop) // prints "[Subclass]\n"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3780 次 |
| 最近记录: |