2017-01-05 15 views
0

以下、クラスがBでジェネリック型があり、ジェネリック型にはサブクラス型の制約があります。別のクラスAでは、辞書プロパティvaluesを作成し、キーはString、値はBです。次に、クラスAには、値が単一の型に制約されないように、辞書の値を返すか設定するメソッドがあります(のタイプはNSObjectのサブクラスです)。しかし、これは、次の2つのエラーがインライン下記の注意生成します。私はNSObjectのサブクラスであり、すべてがOKになるだろうSomeTypeコンパイラに伝えるためにvalues辞書を宣言するの様々な形態をしようとしましたジェネリックスを使用して辞書の値にアクセスするときにコンパイル時のエラーが発生する

class A: NSObject { 

    var values = [String : B]() 

    func get<SomeType: NSObject>(key: String) -> B<SomeType>? { 
     // #1 Error on line below: cannot convert return expression of type 'B<NSObject>?' to return type 'B<SomeType>?' 
     return values[key] 
    } 

    func set<SomeType: NSObject>(key: String, value: B<SomeType>) { 
     // #2 Error on line below: cannot assign value of type 'B<SomeType>' to type 'B<NSObject>?' 
     values[key] = value 
    } 
} 

class B<SomeType: NSObject>: NSObject { 

} 

が、失敗しました。 this questionと同様に、SomeTypeというメソッドがNSObjectというサブクラスとして定義されているため、valuesから設定して取得するときに型が安全であるように見えるため、ちょっと怪しいです。

私はメソッドからジェネリック型を削除して、代わりに<NSObject>の型を強制することができますが、私はhereと同じ問題に遭遇します。

答えて

2

これは、あなたがそれをやっていると思う何をやっていないことがあります。

var values = [String : B]() 

これは[String : B<NSObject>]だ、本当に[String : B]ではありません。 (私は実際にはこれが正当な構文であることに驚いています;それについてのバグレポートを開くように誘惑されるでしょう; BはSwiftの適切なタイプではありません。)これはすでに実現しているかもしれませんが、

2番目の重要な点は、ジェネリック型はSwiftで共変しないということです。 Thing<Cat>は、Thing<Animal>のサブタイプではありません。これにはいくつかのタイプ理論の理由がありますが、これにはいくつかの技術的な実装理由がありますが、重要なのはそれがSwiftでは不可能であるということです。

B種類のさまざまな種類を保持する必要がある場合は、を作成する必要があります。あなたにもAは、一般的な作り、その後、Bタイプのただ一種類を保持する必要がある場合は

class B<SomeType: NSObject>: NSObject { 
    let value: SomeType 

    init(value: SomeType) { 
     self.value = value 
    } 

    func liftGeneric() -> B<NSObject> { 
     return B<NSObject>(value: value) 
    } 
} 

:あなたのケースでは、タイプの消しゴムは、おそらくこのようなものでB<NSObject>である可能性があります。

+0

お返事ありがとうございます。私は型の消しゴムを使用する限り、私は 'get'メソッドからジェネリックを削除して' B ? 'を返し、 'set'メソッドで' values [key] = value.liftGeneric() '?ただし、その場合は、渡された実際の値ではなく、辞書の値のコピーを設定しています。このメソッドを使用して渡された値のインスタンスを設定する方法はありますか? – ospr

+0

いいえ、その場合、元のオブジェクトを保持してメッセージを渡したより複雑なタイプの消しゴムにする必要があります。ほとんどの場合、私はこれに深く踏み込んだ解決策が過度にジェネリゼーションされていることを明らかにしました。明示的な問題を解決する必要があります(今日のコードでは、あなたはいつか問題があるかもしれません)。時にはジェネリックスの恩恵を受けていることもありますが、何年もの間、ジェネリック医薬品なしで多くの優れたソフトウェアを構築しています。 –

+0

(もっと複雑なクラスベースのタイプの消しゴムを作ることについては、明白な問題を見る必要がありますが、そこには良いサイズはありません。それはあなたのためにすべての解決策です。) –

関連する問題