如何以通用方式调用协议上的静态函数?

Sir*_*III 23 protocols swift swift-protocols

是否有必要在协议上声明静态函数?使用协议的客户端必须在符合协议的类型上调用该函数吗?这打破了不必知道符合IMO协议的类型的想法.有没有办法以一种我不必知道符合我的协议的实际类型的方式调用协议上的静态函数?

Luc*_*tti 26

好问题.这是我谦虚的观点:

是否有必要在协议上声明静态函数?

与在协议中声明的实例方法几乎相同.

使用协议的客户端必须在符合协议的类型上调用该函数吗?

是的,与实例功能完全一样.

这打破了不必知道符合IMO协议的类型的想法.

不.看下面的代码:

protocol Feline {
    var name: String { get }
    static func createRandomFeline() -> Feline
    init()
}

extension Feline {
    static func createRandomFeline() -> Feline {
        return arc4random_uniform(2) > 0 ? Tiger() : Leopard()
    }
}

class Tiger: Feline {
    let name = "Tiger"
    required init() {}
}

class Leopard: Feline {
    let name = "Leopard"
    required init() {}
}

let feline: Feline = arc4random_uniform(2) > 0 ? Tiger() : Leopard()
let anotherFeline = feline.dynamicType.createRandomFeline()
Run Code Online (Sandbox Code Playgroud)

我不知道变量里面的实际类型feline.我只知道它确实符合Feline.但是我正在调用静态协议方法.

有一个更好的方法吗?

我知道,您希望调用协议中声明的静态方法/函数,而不创建符合协议的值.

像这样的东西:

Feline.createRandomFeline() // DANGER: compiler is not happy now
Run Code Online (Sandbox Code Playgroud)

老实说,我不知道为什么这是不可能的.

  • 将`static func createRandomFeline() - > Feline`声明为`static func createRandomFeline() - > Self`.现在,你看到原因了吗?:)协议没有`self`,因此你不能调用它的方法. (7认同)

Sir*_*III 5

谢谢@appzYourLife 的帮助!你的回答启发了我的回答。

@appzYourLife 回答了我的问题。我有一个我正在尝试解决的潜在问题,下面的代码解决了我的问题,所以我会在这里发布它,也许它可以帮助我解决相同潜在问题的人:

 protocol MyProtocol {
     static func aStaticFunc()
 }

 class SomeClassThatUsesMyProtocolButDoesntConformToIt {

     var myProtocolType: MyProtocol.Type
     init(protocolType: MyProtocol.Type) {
         myProtocolType = protocolType
     }

     func aFunction() {
         myProtocolType.aStaticFunc()
     }
 }
Run Code Online (Sandbox Code Playgroud)


ilj*_*ljn 5

是的,这是可能的:

迅捷3

protocol Thing {
  static func genericFunction()
}

//... in another file

var things:[Thing] = []

for thing in things {
  type(of: thing).genericFunction()
}
Run Code Online (Sandbox Code Playgroud)

  • 这不是一个通用函数。 (2认同)

acc*_*ews 5

我为这种情况创建了另一个解决方案。恕我直言,这非常干净和简单。

首先,创建用于访问实例类型的协议。

protocol TypeAccessible {
    func type() -> Self.Type
}

extension TypeAccessible {
    func type() -> Self.Type {
        return Swift.type(of: self)
    }
}
Run Code Online (Sandbox Code Playgroud)

然后像这里一样创建你的具体类。关键是你的协议应该符合TypeAccessible协议。

protocol FooProtocol: TypeAccessible {
    static func bar()
}

class Foo: FooProtocol {
    static func bar() { }
}
Run Code Online (Sandbox Code Playgroud)

在呼叫站点将其用作

let instance: FooProtocol = Foo()
instance.type().bar()
Run Code Online (Sandbox Code Playgroud)

对于更多用例,只需确保您的协议符合TypeAccessible即可。