Swift协议符合:候选者具有不匹配类型

Bon*_*nan 8 ios swift

我试图用一些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类型,这正是您想要说的.


the*_*tic 5

您可以做的游乐场示例:

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)