2016-05-03 102 views
1

來概括我試圖創造斯威夫特時,Xcode 7.3(所以雨燕2.2)廣義類,但我似乎無法得到它過去的編譯器:試圖在迅速

protocol Struct1Protocol { 
} 

struct Struct1 { 
    var name1: String 
} 

protocol Struct2Protocol { 
} 

struct Struct2: Struct2Protocol { 
    var name2: String 
} 

class StructDependent<T> { 
    func setupFrom<T:Struct1Protocol>(value: T) { 
     print("we want to setup StructDependent with struct 1") 
    } 

    func setupFrom<T:Struct2Protocol>(value: T) { 
     print("we want to setup StructDependent with struct 2") 
    } 
} 

class A<T> { 
    func test(value: T) { 
     let structInstance = StructDependent<T>() 
     // this gives a compiler error: 
     // Cannot invoke 'setupFrom' with an argument list of type '(T)' 
     structInstance.setupFrom(value) 
    } 
} 

的想法是有一個StructDependent可以從不同的結構設置。如果類已經用兼容的結構體實例化,則類A應該能夠調用setupFrom。像這樣:

let a = A<Struct1>() 
let v = Struct1(name1: "") 
a.test(v) 

我該怎麼辦呢?我在這裏有點受阻,所以所有想法都是受歡迎的。

+0

我不知道那是怎麼回事,一定是在我的複製粘貼緩衝區裏意外。我將示例代碼更正爲我在Xcode中使用的代碼。 –

+0

好吧,但它仍然是一個問題。沒有關於'value:T'的信息告訴編譯器'T'採用了Struct1Protocol或Struct2Protocol。那麼如何在需要Struct1Protocol或Struct2Protocol的地方使用呢? – matt

+0

爲什麼沒有Struct1和Struct2採用_ same_協議?這樣你可以輸入'value:T'作爲採用該協議。 – matt

回答

3

在我看來,你是這樣想的。我會對此案採取更爲簡單的觀點,並且完全不採用泛型;相反,我們只是使用協議作爲一種在兩個結構(就像我們會用一個超如果結構是類)的超類型:

protocol StructProtocol { 
    var name : String {get set} 
    func setup() 
} 

struct Struct1 : StructProtocol{ 
    var name: String 
    func setup() {} 
} 

struct Struct2 : StructProtocol { 
    var name: String 
    func setup() {} 
} 

class StructDependent { 
    func setup(s:StructProtocol) { 
     s.setup() // or not, I don't care... 
     // or you could just switch on the type, e.g.: 
     switch s { 
     case is Struct1: // ... 
     case is Struct2: // ... 
     default: break 
     } 
    } 
} 

class A { 
    func test(value: StructProtocol) { 
     let structInstance = StructDependent() 
     structInstance.setup(value) 
    } 
} 

如果StructDependent 本身真正需要做的這取決於不同的事情在調用setup時,它可以打開實際類型。但是,第一種方法會更好,我們只需按照自己的方式將Struct1和Struct2都知道如何操作即可。

+0

看起來我確實是在反思這一點。謝謝!! –

+0

我修改過,以便Struct1和Struct2都具有'name'屬性,以防你正在考慮使用它。再說一遍,如果這是協議規定的,編譯器會很樂意讓你從它們中任何一個協議的標題下取得它。 – matt

1

你需要在你的泛型類型上加一個類型約束。 您可以對此約束使用全包協議。

protocol StructProtocol { 
} 

protocol Struct1Protocol: StructProtocol { 
} 

struct Struct1: Struct1Protocol { 
var name1: String 
} 

protocol Struct2Protocol: StructProtocol { 
} 

struct Struct2: Struct2Protocol { 
var name2: String 
} 



class StructDependent<T> { 
func setupFrom<T:Struct1Protocol>(value: T) { 
    print("we want to setup StructDependent with struct 1") 
} 

func setupFrom<T:Struct2Protocol>(value: T) { 
    print("we want to setup StructDependent with struct 2") 
} 
} 

class A<T: Struct1Protocol> { 
func test(value: T) { 
    let structInstance = StructDependent<T>() 
    // this gives a compiler error: 
    // Cannot invoke 'setupFrom' with an argument list of type '(T)' 
    structInstance.setupFrom(value) 
} 
} 

let a = A<Struct1>() 
+0

是的,這也是我的第一個建議(在我對原始問題的評論中)。但隨後將奧卡姆剃刀應用於您的答案,我們得到了我的答案。他們實際上是一樣的!涼。 – matt

+0

你的回答也幫助了我,R.P.!很遺憾,我只能在StackOverflow上正確接受一個。 –

+0

我還沒有。我設法讓事情得以編譯,並且我認爲我正在進行中,但是在運行時它不起作用。 我在迷你項目中分離了我的代碼。這一切都與嘗試構建一堆普通的TableView代碼類有關。所以在這個例子中,你可以在這裏下載https://dl.dropboxusercontent.com/u/165243/tableviewgeneralization.zip這裏有一個我想要做的更具體的例子。 任何幫助仍然感激。 –