访问协议实现的静态变量:

huangapple go评论59阅读模式
英文:

Swift: Access to static var of a protocol implementation

问题

I get a compiler error when I try to access a property of my protocol implementation and would like to understand why this is not working:

"Static member 'foo' cannot be used on an 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 an instance of type 'any MyProtocol

I tried to understand the error message. Any instance that conforms to "MyProtocol" should have a (static) var foo. So why am I not allowed to access it?

英文:

I get a compiler error when I try to access a property of my protocol implementation and would like to understand why this is not working:

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

I tried to understand the error message. Any instance that conforms to "MyProtocol" should have a (static) var foo. So why am I not allowed to access it?

答案1

得分: 1

以下是您要翻译的内容:

有两个基本问题。

第一个问题是a.bar是一个实例,根据定义,您不能在实例上使用static成员。您必须指定类型。要调用foo,您需要编写类似以下的内容

    print(ProtocolImplementation.foo)
    //    ^^^^^^^^^^^^^^^^^^^^^^ 这是一个具体类型

这导致了第二个问题,如果编译器只知道一个实例符合某个协议,那么它无法决定要使用哪个符合类型上的静态属性。因此,您不能编写

print(MyProtocol.foo)

因为编译器需要一个具体的类型来获取静态属性。

有办法解决这个问题。一个方法是扩展协议,添加一个仅获取静态属性的实例属性

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

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

print(a.bar.foo) // 打印 2

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

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

可能还有其他更巧妙的方法来实现您想要的功能。

英文:

There are two basic issues.

The first is that a.bar is an instance and by definition you cannot use a static member on an instance. You have to specify the type. To invoke foo you need to write something like

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

This leads to the second problem, if all the compiler knows about an instance is that it conforms to a certain protocol, then it can't decide which static property on which conforming type to use. So you can't write

print(MyProtocol.foo)

because the compiler needs a concrete type from which to get the static property.

There are ways around this. One would be to extend the protocol with an instance property that just gets the static property

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

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

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

Another would be to get the type at runtime

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

There are probably other more clever methods of doing what you want.

答案2

得分: 0

A static property belongs to the type itself, not to an instance.

Therefore you have to call it on the type

print(ProtocolImplementation.foo)
英文:

A static property belongs to the type itself, not to an instance.

Therefore you have to call it on the type

print(ProtocolImplementation.foo)

huangapple
  • 本文由 发表于 2023年4月13日 16:46:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76003440.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定