[英]Generic factory method and type inference
我有以下带有通用工厂方法的 class:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
}
extension Something {
class func zip<A, B>(_ a: A, _ b: B) -> Something<(A, B)> {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
为什么我不能在没有明确指定返回类型的情况下调用zip
?
// ERROR: Cannot invoke `zip` with an argument list of type `(Int, Int)`
let y = Something.zip(1, 2)
// OK: Works but it’s unacceptable to require this on caller's side
let x = Something<(Int, Int)>.zip(1, 2)
感谢您的时间!
你看到这个的原因是这个电话中没有任何内容:
let y = Something.zip(1, 2)
这告诉Swift T
应该是什么。
您的调用隐式指定A
和B
应该是什么,并指定该方法应返回Something<A, B>
。 但那个Something<A, B>
没有连接到Something<T>
。
事实上,你的电话中没有任何东西与T
; T
未指定,因此可能是任何东西。 我的意思是字面意思 - 你实际上可以在Something
之后将(几乎)任意随机类型放在尖括号中并且它将完全相同:
let y = Something<UICollectionViewDelegateFlowLayout>.zip(1, 2)
你真正想做的是以某种方式指定T
必须是一个元组,并且这两个参数与元组的元素具有相同的类型。 不幸的是,Swift目前还没有正确执行此操作所需的功能。 如果语言更复杂,你可以这样说:
extension<A, B> Something where T == (A, B) {
class func zip(a: A, _ b: B) -> Something {
let initial = (a, b)
return Something(initial: initial)
}
}
但是现在,你将不得不处理这个可怕的黑客攻击,它通过毫无意义地重用T
类型参数来工作,这样它就不再处于松散状态:
extension Something {
class func zip<B>(a: T, _ b: B) -> Something<(T, B)> {
let initial = (a, b)
return Something<(T, B)>(initial: initial)
}
}
简而言之,您使用泛型不正确。 它不是实时功能,它是预编译的东西。 如果需要从泛型输入值中创建抽象类,请查看并执行以下操作:
class Abstract<T> {
init(value: T) {
print("inputed value: \(value)")
}
}
class Something {
class func zip<A, B>(value: A, value2: B) -> Abstract<(A, B)> {
print("Something.zip", value, value2)
return Abstract<(A, B)>(value: (value, value2))
}
}
Something.zip(5, value2: 40) // "inputed value: (5, 40)"
T
就这样简单地与A
和B
无关,因此无法推断。
例如。
let z = Something<(String, String)>.zip(1, 2)
let z2 = Something<AnyObject>.zip(1, 2)
工作得很好,可以返回Something<(Int, Int)>
您可以像这样为您的案例引入类型推断:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
class func zip<A, B>(_ a: A, _ b: B) -> Something<T> where T == (A, B) {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
let y = Something.zip(1, 2) //works
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.