具有 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)
这并未表达您对 T
的 NSObject
约束,但您并未在函数本身的实现中使用该约束。
如果这只是一个简化的示例,而您实际上想要为既继承自NSObject
又符合[=的任何类型表达一系列元类型16=] – 你目前不能在 Swift 中表达这个 3.
但是在Swift4中,我们可以用NSObject & Recyclable
的a class existential来表达这个:
func printAllNames(_ things: (NSObject & Recyclable).Type...) {
for thing in things {
print(thing.name)
}
}
混合
我有一个 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
.
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)
这并未表达您对 T
的 NSObject
约束,但您并未在函数本身的实现中使用该约束。
如果这只是一个简化的示例,而您实际上想要为既继承自NSObject
又符合[=的任何类型表达一系列元类型16=] – 你目前不能在 Swift 中表达这个 3.
但是在Swift4中,我们可以用NSObject & Recyclable
的a class existential来表达这个:
func printAllNames(_ things: (NSObject & Recyclable).Type...) {
for thing in things {
print(thing.name)
}
}