比较通用结构类型

时间:2014-11-12 02:24:11

标签: generics swift types struct

如何确定通用结构的两个实例是否属于同一类型?

例如,给定以下结构:

struct FooBar<T> {
    let variable: T
    init(arg: T) {
        variable = arg
    }
}

以下代码段:

let foo = FooBar(1)
let bar = FooBar(1.0)
let baz = FooBar("1")

如何确定foobarbaz是相同还是不同类型?


func areExactType(x: FooBar) -> Bool {
    return self.dynamicType === x.dynamicType
}

这给出了

  

类型'Foo'不符合协议'AnyObject'


func areExactType(x: FooBar) -> Bool {
    return self.dynamicType === x.dynamicType
}

这给出了

  

无法使用类型为'(Foo.Type,Foo.Type)'的参数列表调用'=='


func areExactType(x: FooBar) -> Bool {
    return self is x.dynamicType
}

这给出了三个错误:

  

一行上的连续陈述必须用';'

分隔

(这需要在句点和'dynamicType'之间加一个分号)

  

虚线类型的预期标识符

  

预期表达

3 个答案:

答案 0 :(得分:11)

编辑:

对于过早的回答感到抱歉,它实际上不起作用,因为编译器会在从另一个函数调用时选择不同类型的函数:

func foobar<T,U> (lhs: Foo<T>, rhs: Foo<U>) -> Bool {
    return lhs.sameType(rhs)
}

如果你留在纯粹的Swift领域,以下方法将起作用:

给出一个简单的通用结构

struct Foo<T> {
    let v : T
}

您可以定义一个函数sameType,该函数转到同一类型的Foo,然后返回true

func sameType<T> (a: Foo<T>, b: Foo<T>) -> Bool {
    return true
}

并使用两个不同的Foo s:

重载该函数
func sameType<T,U> (a: Foo<T>, b: Foo<U>) -> Bool {
    return false;
}

编译器将根据参数类型选择一种方法:

let a = Foo(v: 1.0)
let b = Foo(v: "asdf")
sameType(a, b) // false
sameType(a, a) // true

这与struct上的实例方法的工作方式相同:

    func sameType (other: Foo) -> Bool {
        return true
    }

    func sameType<U> (other: Foo<U>) -> Bool {
        return false
    }

如果您混合使用Swift和Objective-C,或者出于其他原因必须依赖动态类型,则会出现意外结果:

import Foundation
let x = NSArray(object: 1)
let y = NSArray(object: "string")
sameType(Foo(v: x[0]), Foo(v: y[0])) // true

结果是正确的,因为because Foo(v: x[0])的类型为Foo<AnyObject>

答案 1 :(得分:6)

Sebastian's answer获得一些灵感,我提出了这个解决方案:

func sameType<L,R>(left: L, right: R) -> Bool {
    if let cast = left as? R {
        return true
    } else {
        return false
    }
}

即使嵌套在接受泛型的函数中,这也有效:

func compare<T,U>(foo: T, bar: U) -> Bool {
    return sameType(foo, bar)
}

但它确实有一些塞巴斯蒂安的答案提到的垮台。也就是说,如果您从Objective-C集合中检索了您的值,则它们的类型都为AnyObject。此外,如果我将sameType函数嵌套在一个参数不是泛型的函数中,例如:

func compare(foo: Any, bar: Any) -> Bool {
    return sameType(foo, bar)
}

此处的sameType功能将始终返回true。就foo而言,barsameType的类型是Any,而不是我可能将其转发到的最具体类型。


它也可能值得注意的是,如果我尝试将其嵌套为实例方法,Xcode会崩溃。再次阅读, Xcode崩溃。不会产生不良结果&#34;。应用程序崩溃。

例如:

func sameType<L,R>(left: L, right: R) -> Bool {
    if let cast = left as? R {
        return true
    } else {
        return false
    }
}

struct Foo<T> {
    func sameType<U>(bar: U) -> Bool {
        return sameType(self, bar)
    }
}

let x = Foo<Int>()
let y = Foo<Float>()

if x.sameType(y) {
    println("x is a y")
}

此代码段崩溃了Xcode。我不知道为什么......但确实......

如果我们改为写:

if sameType(x,y) {
    println("x is a y")
}

Xcode编译并运行得很好。

答案 2 :(得分:2)

如果我没有误解,你不想知道FooBar类型的变量是否属于同一类型(因为它们是),你想要检查它们是否使用相同的泛型类型。

由于struct已包含泛型类型的属性,因此可以将其用于类型比较,而不是使用struct本身:

func areExactType<U>(x: FooBar<U>) -> Bool {
    return x.variable is T
}

我在游乐场测试过,它适用于基本数据类型,数组,字典等。 缺点是,为了使其工作,结构必须具有泛型类型的属性。