Generics 在Swift泛型中强制使用超类

Generics 在Swift泛型中强制使用超类,generics,swift,Generics,Swift,我试图实现一种新方法来连接两个数组,将包含公共数据类型的数组返回给另外两个 为了保持清晰,我希望有一种方法可以执行以下操作(知道语法不正确……): @infix func+(左:数组,右:数组) ->排列{ //连接两个数组 } 始终认为编译器能够检测两个类的共同祖先类型。如果这实际上是不可能的,那么正确的方法是什么?使“超级”类型显式化?您可以使用:语法,如下所示: // The parameter must be a UIViewController, or subclass func c

我试图实现一种新方法来连接两个
数组
,将包含公共数据类型的
数组
返回给另外两个

为了保持清晰,我希望有一种方法可以执行以下操作(知道语法不正确……):

@infix func+(左:数组,右:数组)
->排列{
//连接两个数组
}

始终认为编译器能够检测两个类的共同祖先类型。如果这实际上是不可能的,那么正确的方法是什么?使“超级”类型显式化?

您可以使用
语法,如下所示:

// The parameter must be a UIViewController, or subclass
func changeViewColor<T: UIViewController>(vc: T) {
    vc.view.backgroundColor = UIColor.redColor()
}
//参数必须是UIViewController或子类
func changeViewColor(vc:T){
vc.view.backgroundColor=UIColor.redColor()
}

斯威夫特的类型推断比你想象的要聪明。秘密在于查看零合并运算符的签名
??

func ??<T>(optional: T?, defaultValue: @autoclosure () -> T) -> T
func ??<T>(optional: T?, defaultValue: @autoclosure () -> T?) -> T?
这可以编译并工作,但是
a
的类型是
Any
(实际上是一个协议)。在某些情况下,您需要向编译器提供类型证据,而在某些情况下则不需要。如果这些类型共享一个不是协议的共同祖先,那么似乎不需要证据。您可能认为
受到了编译器的特殊处理,但事实并非如此。你可以很容易地滚动你自己的

为了达到你的目的,你这样想太多了。(就像我遇到类似问题时一样)你只需要一种类型

如果我们将您的
+
实现为一个函数,它将如下所示:

func joinArrays<T>(array1: [T], array2: [T]) -> [T] {
    return array1 + array2
}

class Base {}
class Derived1 : Base {}
class Derived2 : Base {}

let a1 = [Derived1(), Derived1()]
let a2 = [Derived2(), Derived2()]
let a = joinArrays(a1, a2)
func联合数组(array1[T],array2[T])->[T]{
返回数组1+数组2
}
类基{}
类Derived1:基{}
类Derived2:基{}
设a1=[Derived1(),Derived1()]
设a2=[Derived2(),Derived2()]
设a=joinArray(a1,a2)
a
的类型是
Array
,因为它是泛型类型参数最接近的公共祖先


我用这种“类型提升”来创建各种复杂的聚合/一元运算符,如la Haskell。唯一的问题是Swift不支持泛型类型参数的协方差。

super
替换为
。正如在
T:X
中所说,T必须是X,其中X是一个协议或类。这样行吗?如果是这样,请张贴一些真实的代码。我无法使用语法@中缀func+(左:T[],右:U[])->X[]{…有错误“类型U被限制为非协议类型X”@Grimxn很抱歉回答延迟。我收到一个错误(类型T被限制为非协议类型X).但我必须承认你的解决方案看起来不错。为什么这不可能?看起来编译器确实无法推断两个类的共同祖先
let i: Int? = 3
let s: String? = "3"
let a: Any? = i ?? s
func joinArrays<T>(array1: [T], array2: [T]) -> [T] {
    return array1 + array2
}

class Base {}
class Derived1 : Base {}
class Derived2 : Base {}

let a1 = [Derived1(), Derived1()]
let a2 = [Derived2(), Derived2()]
let a = joinArrays(a1, a2)