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
谢谢!
您只能使用 Any
和 switch
来实现这种动态行为,后者将值强制转换回来,以便将返回的类型用作类型化变量:
// 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
}
枚举的优点是编译器会检查所有情况。
这可能吗?
场景是,我想要一个函数接受一个与该函数的通用约束无关的参数,并且 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
谢谢!
您只能使用 Any
和 switch
来实现这种动态行为,后者将值强制转换回来,以便将返回的类型用作类型化变量:
// 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
}
枚举的优点是编译器会检查所有情况。