具有 mixin 的多个 类 函数

Function with multiple classes that have a mixin

混合

我有一个 mixin,它打印将 class 名称作为 String 分配给实例变量。

import Foundation

protocol Recyclable {
    static var name: String { get }
}

extension Recyclable {
    static var name: String {
        return String(describing: Self.self)
    }
}

有两个 class 实现了混入:

class One: NSObject, Recyclable { }
class Two: NSObject, Recyclable { }

所以如果我想打印 class 名字,我可以

One.self.name // "One"

这非常有效。现在让我们更深入一些。

打印多个给定的通用函数 classes

将其放入函数中以打印所有给定 classes 的名称。它必须是通用的,因为它可以接受任何符合可回收 protocol.

的 class
func printAllNames<T: NSObject>(_ things: T.Type...) where T: Recyclable {
    for thing in things {
        print(thing.name)
    }
}

如果我只将它用于一个 class,它会按预期工作。

printAllNames(One.self) // "One"

但与多个一起使用时,会出错

printAllNames(One.self, Two.self)

Playground execution failed: error: GenericMixins.playground:20:1: error: generic parameter 'T' could not be inferred printAllNames(One.self, Two.self)


关于可能发生的事情的任何提示?

游乐场:https://www.dropbox.com/sh/q0b5b3oo0luj471/AABSG2QEOIj_SBsvtv7cEv-Ka?dl=0

我终于搞清楚了。正确的做法是让函数接受任何东西,然后检查接受的东西是否符合协议。

函数应该是

func printAllNames(_ things: AnyObject...) {
    for thing in things {
        if let klass = thing.self as? Recyclable.Type {
            print(klass.name)
        }
    }
}

然后它按预期工作

printAllNames(One.self, Two.self)

One

Two


已更新游乐场:https://www.dropbox.com/sh/9sjboo3lfu83662/AAC9CKn_dU_wrihCvKUfujQ7a?dl=0

@dirtydanee says 一样,问题是通用占位符 T 代表一个 单一 类型,要在函数的调用点满足.因此,可变参数 T.Type... 表示 相同 类型 T.

的一系列元类型

解决办法很简单,就是有一个Recyclable.Type...参数,它表达了一系列any类型的元类型,符合Recyclable:

func printAllNames(_ things: Recyclable.Type...) {
    for thing in things {
        print(thing.name)
    }
}

printAllNames(One.self, Two.self)

这并未表达您对 TNSObject 约束,但您并未在函数本身的实现中使用该约束。


如果这只是一个简化的示例,而您实际上想要为既继承自NSObject又符合[=的任何类型表达一系列元类型16=] – 你目前不能在 Swift 中表达这个 3.

但是在Swift4中,我们可以NSObject & Recyclablea class existential来表达这个:

func printAllNames(_ things: (NSObject & Recyclable).Type...) {
    for thing in things {
        print(thing.name)
    }
}