2016-08-11 22 views
3

XCode 7.3.1でSwift 2.2を使用していて、別のGeneric関数からGeneric関数を呼び出そうとしています。Swift Generic関数が別のGeneric関数を呼び出す

コード

class Thing1 { 
    let variable: SomeProtocol 
    init<A: SomeProtocol>(variable: A) { 
      self.variable = variable 
      self.add1(self.variable) 
    } 

    func add1<A: SomeProtocol>(stuff: A) { 
      let thing: Thing2 = Thing2() 
      thing.add2(stuff) 
    } 

} 

class Thing2 { 
    func add2<A: SomeProtocol>(stuff: A) { 

    } 
} 

protocol SomeProtocol { } 


add1("a") // Cannot invoke 'add1' with an argument list of type '(String)' 
add1(4) // Cannot invoke 'add1' with an argument list of type '(Int)' 

私はエラーを取得します。

'Cannot invoke add with an argument of list type '(Whatever type I used to call the function)'' 
+0

コードを少し整理しました。プレイグラウンドではうまくコンパイルされますが、あなたが「add1」を呼び出そうとすると、あなたはそれを許可しません。 –

+0

@CodyWeaverあなたが得ることができるコンパイルに近いほどの最小限の例を投稿してください。このように、私たちはすべて、「SomeProtocol」、「Thing」などの独自の実装を思いつくことなく、一貫してテストしています。 – Alexander

+0

何が起こっているのかを明確にするためのコードを追加しました。 –

答えて

2

問題はabstract types in Swift don't necessarily conform to themselvesがあることである - 準拠していること、したがって、あなたが具体的な型指定されたものとしてSomeProtocol入力されたものを使用することはできません(あなたのadd1汎用関数が引数として期待しているものです)。

それはジェネリックだから、それはそれゆえ、あなたに渡すことができSomeProtocolに準拠して、具体的なもの、としてタイプだとして、あなたのケースでは、最も簡単な解決策は、したがって、単にむしろvariable財産よりも、一般的なvariable引数を使用することですadd1機能:

init<A: SomeProtocol>(variable: A) { 
    self.variable = variable 
    add1(variable) 
} 

しかし、後でラインダウン問題のこれらの種類を防ぐために、あなたはあなたのvariableプロパティが与えられたの生涯を通じて一定の種類のものであるべきであると仮定して、あなたのクラスは、一般的なことを検討することをお勧めしますThing1インスタンス:

あなたが別の variable種類の異なる Thing1インスタンスを混在させることができ
class Thing1<A:SomeProtocol> { 

    let variable: A 

    init(variable: A) { 
     self.variable = variable 
     add1(variable) 
    } 

    func add1(stuff: A) { 
     let thing = Thing2() 
     thing.add2(stuff) 
    } 
} 

それとも、あなたはSomeProtocolに準拠する任意タイプを動作するようになります抽象型SomeProtocolを使用するようにコードをリファクタリング可能性があり(例えば配列):

class Thing1 { 

    let variable: SomeProtocol 

    init(variable: SomeProtocol) { 
     self.variable = variable 
     add1(variable) 
    } 

    func add1(stuff: SomeProtocol) { 
     let thing = Thing2() 
     thing.add2(stuff) 
    } 
} 

class Thing2 { 
    func add2(stuff: SomeProtocol) { 

    } 
} 

あなたは常に、see this great WWDC talk for more infoを抽象型を使用して付属して余分なコストを認識しておく必要がありますが。

0

StringIntに拡張子を追加し、Thing1オブジェクトを構築し、それが動作します:

extension String: SomeProtocol{} 
extension Int: SomeProtocol{} 

Thing1(variable: "a").add1("a") 
Thing1(variable: 2).add1(4) 
関連する問題