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

19

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

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只能用作泛型约束,因为它具有“Self”或关联类型的要求。

好的,所以它只能在有关联类型要求的情况下使用(它确实有),但出现了错误??真是令人糊涂!

我不确定编译器试图告诉我什么......


可能是[无法将类实例分配给其协议类型?]的重复问题(https://dev59.com/poTba4cB1Zd3GeqP1RpS)。 - Antonio
2个回答

17
假设我们将 Thing 的实例放入数组 foos 中,会发生什么?
protocol Foo {
    associatedtype 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,你能告诉我应该向bar传递字符串还是整数吗?

foo.bar("foo") 或者 foo.bar(1)

Swift不支持这样的操作。

因此,它只能用作通用约束。

什么情况下需要这样的协议呢?

例如:

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
        }
}

2

我一直在尝试理解如何实现该协议,因此一直在使用您的代码。我发现,由于Typealias仅仅是别名而不是类型本身,因此无法将其用作通用类型。所以,如果您将Typealias声明在协议和类之外,您就可以在代码中有效地使用它而不会遇到任何问题。

注意:在Typealias的声明中,它的类型为Int,这样您就可以始终使用别名而不是Int类型,并使用所有相关的方法和函数。

以下是我如何使其工作的:

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

在这段代码中,BazType只是Int而不是变量类型。 - Edward Ashak

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接