我有以下协议和符合它的类:
- protocol Foo{
- typealias BazType
- func bar(x:BazType) ->BazType
- }
- class Thing: Foo {
- func bar(x: Int) -> Int {
- return x.successor()
- }
- }
当我尝试创建一个foos的数组时,我得到一个奇怪的错误:
- var foos: Array<Foo> = [Thing()]
Protocol Foo can only be used as a generic constraint because it has
Self or associated type requirements.
好的,所以它只能被使用,如果它有一个关联的类型要求(它做),但由于某些原因这是一个错误? WTF?
我不知道我完全明白编译器试图告诉我什么
假设我们可以把一个Thing的例子放在数组foos中,会发生什么?
- protocol Foo {
- typealias BazType
- func bar(x:BazType) -> BazType
- }
- class Thing: Foo {
- func bar(x: Int) -> Int {
- return x.successor()
- }
- }
- class AnotherThing: Foo {
- func bar(x: String) -> String {
- return x
- }
- }
- var foos: [Foo] = [Thing()]
因为AnotherThing也符合Foo,所以我们也可以把它放在foos中.
- foos.append(AnotherThing())
现在我们从foos中随机抓取一个foo.
- let foo = foos[Int(arc4random_uniform(UInt32(foos.count - 1)))]
我要调用方法栏,你能告诉我,我应该发送一个字符串或一个整数到bar吗?
foo.bar(“foo”)或foo.bar(1)
斯威夫特不能.
所以它只能用作一般的约束.
什么场景需要这样的协议?
例:
- class MyClass<T: Foo> {
- let fooThing: T?
- init(fooThing: T? = nil) {
- self.fooThing = fooThing
- }
- func myMethod() {
- let thing = fooThing as? Thing // ok
- thing?.bar(1) // fine
- let anotherThing = fooThing as? AnotherThing // no problem
- anotherThing?.bar("foo") // you can do it
- // but you can't downcast it to types which doesn't conform to Foo
- let string = fooThing as? String // this is an error
- }
- }