swift 静态成员“currency”不能用于协议元类型“SomeProtocol.Type”

7fyelxc5  于 2023-06-28  发布在  Swift
关注(0)|答案(1)|浏览(129)

我先给予你一些背景。我正在尝试创建一个函数,该函数接受任何符合协议(SomeProtocol)的类型作为参数。因此,我创建了一个名为currency的静态方法的struct,这个struct符合SomeProtocol,但是,当我试图将该方法作为泛型函数的参数传递时,我得到了这个错误:静态成员“currency”不能用于协议元类型“SomeProtocol. Type”。
我只是尝试重新创建SwiftUI代码:
Text(20.0, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
阅读文档,上面的函数是一个泛型init(),它采用符合某些协议的泛型类型。
init<F>(_ input: F.FormatInput, format: F) where F : FormatStyle, F.FormatInput : Equatable, F.FormatOutput == String
因此,.currency()是一个静态方法,它来自FloatingPointFormatStyle.Currency,一个符合FormatStylestruct
我的问题是,为什么这在SwiftUI中起作用(将一个符合协议的结构体中的静态方法作为参数传递给一个接受任何符合协议的类型的函数),而不是在我自己的例子中:

protocol SomeProtocol {
    associatedtype SomeType: SomeProtocol
    var a: String { get }
    var b: String { get }
    static func currency(x: Int) -> SomeType
}

func someTest<T>(x: T) -> String where T: SomeProtocol{
    return "this works!"
}

struct AnotherType: SomeProtocol {
    let a = "Test"
    let b = "someTest"

    static func currency(x: Int) -> AnotherType {
        return AnotherType()
    }
}

someTest(x: .currency(x: 20))
mzsu5hc0

mzsu5hc01#

请注意,.currency(...)是隐式成员表达式。
隐式成员表达式是一种在类型推断可以确定隐式类型的上下文中访问类型成员(如枚举情况或类型方法)的缩写方式。
Swift只知道参数x需要某个SomeProtocol类型,但不知道是哪一个。所以它认为你的意思是:

someTest(x: SomeProtocol.currency(x: 20))

这无效。您调用的是哪个实现的currencySomeProtocol中声明的currency方法没有实现!
您只能在协议的特定实现中调用currency,例如:AnotherType.currency(x: 20)
请注意,内置currency的文档并没有说“必需”或“提供默认实现”之类的话。SwiftUI所做的是对包含currency实现的协议进行扩展,而不是制定协议要求:

extension SomeProtocol {
    static func currency(x: Int) -> AnotherType {
        return AnotherType()
    }
}

但这仍然不够。您仍然无法执行SomeProtocol.currency(...)。如果currency使用协议的一些静态需求会怎么样?Swift不知道是否有,或者currency是否使用它们。
所以你实际上需要:

extension SomeProtocol where Self == AnotherType {
    static func currency(x: Int) -> AnotherType {
        return AnotherType()
    }
}

现在Swift知道.currency(x: 20)的意思是AnotherType.currency(x: 20)
请注意,SomeType关联类型是不必要的。如果需要,可以添加涉及该内容的进一步约束,但这类隐式成员表达式并不一定有效。

相关问题