2015-08-18 46 views
1

這可能嗎?Swift 2.0 - 通用工廠函數,返回通過函數執行確定的類型

的情況是,我想要一個函數採取一個不相關的參數給這個函數的泛型約束,並返回一個未知的結果類型依賴於上述說法。這些類型彼此沒有任何關係。一個可能是一個字符串,一個可能是一個int,一個可能是一個字符串等數組。

我已經在協議中使用typealias進行了實驗,並且每個符合它的對象都設置了它自己的類型,並且在其工作中使用類型別名。

我有這個實驗的協議:

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) 

不過,我得到一個錯誤信息,

「不能援引 'GETIT' 類型的參數列表 '(INT)'」。

我得到的編譯器有問題搞清楚正是我想要的返回類型是什麼,這樣的話,我想提供一個封閉該T: BaseFunctionality映射到其持有的財產。

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 
}) 

然而,這會導致瘋狂的事情發生在操場上......(崩潰)

有沒有人對如何實現這一神奇的功能與在編譯時未知的返回類型的任何想法?

這裏的swiftstub:http://swiftstub.com/800198020/?v=beta

謝謝!

回答

1

只能達到這樣的動態行爲與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 
} 
+0

感謝@Qbyte!我最終採取了一種根本不同的方法來解決我的問題(這個例子是從域中抽象出來的) – salguodnz

2

正如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 
} 

枚舉的優點是編譯器會檢查你所有的情況。