我迅速具有以下功能:
func test<C1,C2>(val1: C1, val2: C2) {
}
但是我想使用where
来约束此功能,直到C2
是C1
的子类时。我尝试过这样的事情:
func test<C1,C2>(val1: C1, val2: C2) where C2: C1 {
}
但是它不起作用,并显示错误Type 'C2' constraint to non-protocol, non-class type 'C1'
。知道我应该怎么做吗?
答案 0 :(得分:0)
:
表示 type constraint:
类型约束指定类型参数必须从特定的类继承,或者符合特定的协议或协议组合。
不幸的是,这仅允许指定符合已知类或协议,而不能符合其他泛型类型的类型。
例如:
class C {}
func test1<C1,C2:C1>(val1: C1, val2: C2) { // Not valid C1 is a generic
}
func test2<C1,C2:C>(val1: C1, val2: C2) { // Valid since C is a known type
}
这同样适用于进一步约束类型或关联类型的 where
子句。
func test3<C1,C2>(val1: C1, val2: C2) where C2:C1 { // Not valid C1 is a generic
}
func test4<C1,C2>(val1: C1, val2: C2) where C2:C { // Valid since C is a known type
}
where 子句可以是关于 :
的类型一致性,也可以是关于与 ==
的已知类型具有相同的类型。
当已知类型起作用时,语言设计允许您有专门的实现:
func test5<C1,C2>(_ val1: C1, _ val2: C2) {
print ("general test5")
}
func test5<C1,C2:C>(_ val1: C1, _ val2: C2) {
print ("special case of test5")
}
let p1="Hello world!"
let p2=12
class MyClass:C {}
let p3 = MyClass()
test5(p1,p2) // ---> general test5
test5(p1,p3) // ---> special case of test5
但是此功能对已知类型的限制阻止了定义专门的实现,以防一种类型是另一种类型的子类型。
这可能是有充分理由的。如果允许符合泛型类型,则可能有不止一种合适的特化,编译器将没有任何规则可供选择。假设示例,将具有泛型一致性的 与另一个泛型相加:
func test5<C1,C2>(_ val1: C1, _ val2: C2) where C2:C1 {
print ("super special case of test5")
}
在这个假设的例子中,编译器不知道选择哪个特化test5(p1,p3)
。
但是,您可以实现两种类型的函数并在函数体中处理特殊的一致性情况:
func test<C1,C2>(_ object1: C1, _ object2: C2){
let concreteType1 = type(of: object1)
let concreteType2 = type(of: object2)
if object2 is T { // check if C2 conforms to C1
print ("\(concreteType2) conforms to \(concreteType1)")
}
else {
print ("\(concreteType2) is incompatible with \(concreteType1)")
}
}
请注意,根据您要执行的操作,您还可以考虑 as?
强制转换:
if let object3 : C1 = object2 as? C1 { // check if C2 is castable to C1
let concreteType3 = type(of: object3)
print (concreteType1, concreteType2, concreteType3)
}