无法在Swift中创建符合协议的类型数组

时间:2014-11-11 13:13:40

标签: swift protocols associated-types

我有以下协议和符合它的类:

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()]
  

协议Foo只能用作通用约束,因为它具有   自我或相关类型要求。

好的,所以只有在它有相关的类型要求时才能使用它(它确实如此),但由于某种原因这是一个错误? WTF?!

我不确定我是否完全理解编译器试图告诉我的内容......

2 个答案:

答案 0 :(得分:15)

让我们说,如果我们可以将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())

现在我们随机从foo抓取foos

let foo = foos[Int(arc4random_uniform(UInt32(foos.count - 1)))]

我打算调用方法bar,你能告诉我应该发送一个字符串或整数到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
        }
}

答案 1 :(得分:1)

我一直在玩你的代码试图了解如何实现协议。我发现你不能将Typealias用作泛型类型,因为它只是一个别名而不是一个类型。因此,如果您在协议和类之外声明Typealias,则可以在代码中有效地使用它,而不会出现任何问题。

注意: Typealias在其声明中具有Int类型,这样您始终可以使用别名而不是Int类型并使用其所有关联的方法和函数。< / p>

以下是我如何使其发挥作用:

typealias BazType = Int

protocol Foo{
  func bar(x:BazType) -> BazType
}

class Thing: Foo {
  func bar(x: BazType) -> BazType {
    return x.successor()
  }
}

let elements: Array<Foo> = [Thing(), Thing()]