首页 文章

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

提问于
浏览
15

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

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只能用作通用约束,因为它具有Self或相关类型要求 .

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

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

2 回答

  • 1

    比方说,如果我们可以将 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 ,你能告诉我我应该发送一个字符串或整数到 bar 吗?

    foo.bar("foo")foo.bar(1)

    斯威夫特不能 .

    所以它只能用作通用约束 .

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

    Example:

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

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

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

相关问题