Swift 2.0 - 通用工厂函数 returns 由函数实现确定的类型

Swift 2.0 - generic factory function that returns a type determined by implementation of function

这可能吗?

场景是,我想要一个函数接受一个与该函数的通用约束无关的参数,并且 return 一个依赖于所述参数的未知类型的结果。这些类型彼此之间没有任何关系。一个可以是字符串,一个可以是int,一个可以是字符串数组等等。

我已经在协议中使用类型别名对此进行了试验,每个符合它的对象都会设置自己的类型,并在其工作中使用类型别名。

我已经将此作为协议进行了试验:

protocol BaseFunctionality {
    typealias ReturnType
    var property: ReturnType { get set }
    func getData() -> ReturnType
}

然后我有一对符合类:

class StringClass: BaseFunctionality {
    typealias ReturnType = String
    var property: ReturnType = "HELLO WORLD"
    func getData() -> ReturnType {
        return property
    }
}

class IntClass: BaseFunctionality {
    typealias ReturnType = Int
    var property: ReturnType = 12345
    func getData() -> ReturnType {
        return property
    }
}

所以,我想到的是:

func getIt<T: BaseFunctionality>(int: Int) -> T.ReturnType {
    if (int == 0) {
        let stringClass = StringClass()
        return stringClass.getData() as! T.ReturnType // for some reason I have to as! this
    } else {
        let intClass = IntClass()
        return intClass.getData() as! T.ReturnType // same as above comment
    }
}

并这样称呼它:

let testing = getIt(1)

但是,我收到一条错误消息,

"Cannot invoke 'getIt' with argument list of type '(int)'".

我知道编译器在弄清楚我到底想要什么作为 return 类型时遇到问题,所以我想提供一个将 T: BaseFunctionality 映射到 [=61] 的闭包=] 它成立。

func getIt<T:BaseFunctionality, U where U == T.ReturnType>(int:Int, unwrapType: T -> U ) -> U {
    if (int == 0) {
        let source = StringClass()
        return unwrapType(source as! T) // for some reason, source is not a valid T
    }
    else {
        let source = IntClass()
        return unwrapType(source as! T) // see above comment
    }
}

签名中对U的约束可能有问题,但我尝试了多种..

例如,我的称呼方式是这样的。

let data = getIt(1, mapToType: {(unwrapType) -> String in
    return unwrapType.property  as String
})

然而,这会导致操场上发生疯狂的事情......(崩溃)

有没有人知道如何在编译时使用未知的 return 类型实现这个神奇的功能?

此处为 swiftstub:http://swiftstub.com/800198020/?v=beta

谢谢!

您只能使用 Anyswitch 来实现这种动态行为,后者将值强制转换回来,以便将返回的类型用作类型化变量:

// the function
func getIt(i: Int) -> Any {
    if i == 0 {
        return "Hello"
    } else {
        return 42
    }
}

// usage
switch getIt(0) {
case let x as Int:
    // use the return value as Int
case let str as String:
    // use the return value as String
default: break
}

正如Qbyte所说或

enum TextOrNum {
    case Text(s: String)
    case Num(x: Int)
}

func getIt(i: Int) -> TextOrNum {
    if i == 0 {
        return .Text("Hello")
    } else {
        return .Num(42)
    }
}

// usage
switch getIt(0) {
case let .Num(x):
    // use x return value as Int
case let .Text(s):
    // use s return value as String
}

枚举的优点是编译器会检查所有情况。