Swift 将通用类型限制为 Type
Swift restrict generic type to Type
如何将泛型类型限制为类型,而不是类型的实例?
如果我有 class:
class SomeClass<T: SomeProtocol> {}
如何确保 T
只是 AnyClass
的一个实例(这只是 AnyObject.Type
)
我的协议只有静态方法,为了调用这些方法我必须做 instance.dynamicType.protocolMethod
而我想做 someType.protocolMethod
protocol P {
static func foo()
}
class A : P {
static func foo() {
print("A class")
}
}
class B : P {
static func foo() {
print("C class")
}
}
var type1 = A.self
var type2 = B.self
func check(cls: AnyClass)->Void {
switch cls {
case is A.Type:
A.foo()
case is B.Type:
B.foo()
default:
break
}
}
check(type1) // A class
check(type2) // C class
let i = Int.self // Int.Type
let ao = AnyObject.self // AnyObject.Protocol
let ac = AnyClass.self // AnyClass.Protocol
let p = P.self // P.Protocol
let f = check.self // (AnyClass)->Void
编辑
protocol P {
static func f()
}
class A : P {
static func f() {
print("A")
}
}
class B : P {
static func f() {
print("B")
}
}
func f(cls: P.Type) {
cls.f()
}
f(A) // A
f(B) // B
class Test<T: P> {
func foo() {
T.f()
}
}
Test<A>().foo() // A
Test<B>().foo() // B
AFAIK,Swift 不允许您将元类型用作通用类型。 (我相信这与 Sam Giddins wished for in Swift 3 的思路一致。)
但是,您可以将其用作值。不要将 T
设为类型参数,而是将其设为 属性:
protocol SomeProtocol {
static func foo()
}
struct Concrete: SomeProtocol {
static func foo() {
print("I am concrete")
}
}
class SomeClass {
let T: SomeProtocol.Type
init(T: SomeProtocol.Type) {
self.T = T
}
func go() {
T.foo() // no need for dynamicType
}
}
SomeClass(T: Concrete.self).go()
如果如您所说,您的协议仅包含静态方法,那么这就足够了。但是,如果您需要将泛型参数绑定到类型,那也是可能的:
class SomeClass<U: SomeProtocol> {
let T: U.Type
init(T: U.Type) {
self.T = T
}
func go(value: U) {
T.foo()
}
}
SomeClass(T: Concrete.self).go(Concrete())
如何将泛型类型限制为类型,而不是类型的实例?
如果我有 class:
class SomeClass<T: SomeProtocol> {}
如何确保 T
只是 AnyClass
的一个实例(这只是 AnyObject.Type
)
我的协议只有静态方法,为了调用这些方法我必须做 instance.dynamicType.protocolMethod
而我想做 someType.protocolMethod
protocol P {
static func foo()
}
class A : P {
static func foo() {
print("A class")
}
}
class B : P {
static func foo() {
print("C class")
}
}
var type1 = A.self
var type2 = B.self
func check(cls: AnyClass)->Void {
switch cls {
case is A.Type:
A.foo()
case is B.Type:
B.foo()
default:
break
}
}
check(type1) // A class
check(type2) // C class
let i = Int.self // Int.Type
let ao = AnyObject.self // AnyObject.Protocol
let ac = AnyClass.self // AnyClass.Protocol
let p = P.self // P.Protocol
let f = check.self // (AnyClass)->Void
编辑
protocol P {
static func f()
}
class A : P {
static func f() {
print("A")
}
}
class B : P {
static func f() {
print("B")
}
}
func f(cls: P.Type) {
cls.f()
}
f(A) // A
f(B) // B
class Test<T: P> {
func foo() {
T.f()
}
}
Test<A>().foo() // A
Test<B>().foo() // B
AFAIK,Swift 不允许您将元类型用作通用类型。 (我相信这与 Sam Giddins wished for in Swift 3 的思路一致。)
但是,您可以将其用作值。不要将 T
设为类型参数,而是将其设为 属性:
protocol SomeProtocol {
static func foo()
}
struct Concrete: SomeProtocol {
static func foo() {
print("I am concrete")
}
}
class SomeClass {
let T: SomeProtocol.Type
init(T: SomeProtocol.Type) {
self.T = T
}
func go() {
T.foo() // no need for dynamicType
}
}
SomeClass(T: Concrete.self).go()
如果如您所说,您的协议仅包含静态方法,那么这就足够了。但是,如果您需要将泛型参数绑定到类型,那也是可能的:
class SomeClass<U: SomeProtocol> {
let T: U.Type
init(T: U.Type) {
self.T = T
}
func go(value: U) {
T.foo()
}
}
SomeClass(T: Concrete.self).go(Concrete())