Swift:访问协议实现的静态var

57hvy0tb  于 2023-04-19  发布在  Swift
关注(0)|答案(2)|浏览(134)

当我尝试访问我的协议实现的属性时,我得到了一个编译器错误,我想知道为什么这不起作用:
Static member 'foo' cannot be used on instance of type 'any MyProtocol'

protocol MyProtocol {
    static var foo: Int { get }
}

struct ProtocolImplementation: MyProtocol {
    static let foo: Int = 2
}

struct HoldsAProtocolImplementation {
    var bar: MyProtocol
}

let a = HoldsAProtocolImplementation(bar: ProtocolImplementation())
print(a.bar.foo)  // error: Static member 'foo' cannot be used on instance of type 'any MyProtocol

我试图理解错误消息。任何符合“MyProtocol”的示例都应该有一个(静态)var foo。那么为什么不允许我访问它?

ffscu2ro

ffscu2ro1#

有两个基本问题。
首先,a.bar是一个示例,根据定义,您不能在示例上使用static成员。您必须指定 type。要调用foo,您需要编写如下内容

print(ProtocolImplementation.foo)
    //    ^^^^^^^^^^^^^^^^^^^^^^ this is a concrete type

这导致了第二个问题,如果编译器只知道一个示例符合某个协议,那么它就不能决定使用哪个符合类型的静态属性。

print(MyProtocol.foo)

因为编译器需要一个具体类型来获取静态属性。
有很多方法可以解决这个问题,其中一个方法是用一个示例属性来扩展协议,这个示例属性只获取静态属性

protocol MyProtocol 
{
    static var foo: Int { get }
}

extension MyProtocol
{
    var foo: Int { Self.foo }
}

print(a.bar.foo) // prints 2

另一种方法是在运行时获取类型

print(type(of: a.bar).foo)

也许还有其他更聪明的方法来做你想做的事情。

iaqfqrcu

iaqfqrcu2#

静态属性属于类型本身,而不属于示例。
因此你必须在类型上调用它

print(ProtocolImplementation.foo)

相关问题