に私は、フォームの一般的なクラスを持っている:継承、ジェネリック、およびプロトコルは、スウィフト
class BaseClass<T> {
var prop: T
...
}
私は、フォームの複数のサブクラスを持っている:
class SubClassOne: BaseClass<SomeSubClass> {
...
}
class SubClassTwo: BaseClass<SomeOtherSubClass> {
...
}
型パラメータSomeSubClass
とSomeOtherSubClass
どちらも共通の基本クラスSomeBaseClass
を継承しています。
ここで、SubClassOne
とSubClassTwo
の両方のインスタンスを格納する変数を定義します。値を代入しようとしたとき
var obj: BaseClass
var obj: BaseClass<SomeBaseClass>
var obj: BaseClass<Any>
しかし、エラーCannot assign value of type 'SubClassOne' to type ...
でエラーReference to generic type 'BaseClass' requires arguments in <...>
、および他の2つの結果の最初の試みの結果:私は多くの可能性を試してみました。
var testArray = [SubClassOne(), SubClassTwo()]
しかし、これでもエラー
Heterogeneous collection literal could only be inferred to [Any]; add explicit type annotation if this is intentional
で、その結果、失敗しました:私も、配列を初期化することにより、私のためにタイプを推測するにスウィフトコンパイラをだましてみました。実際に、両方のサブクラスの格納に成功する唯一の型注釈は
Any
または
AnyObject
です。より具体的なタイプでこれらのインスタンスを格納することは可能ですか?そうでない場合、なぜですか?
これが重要な理由は、最終的には、格納された変数obj
からプロパティprop
を取得したいということです。 obj
がAny
として保存されている場合は、私はそうすることができません。また、プロパティにアクセスしようとしているメソッド自体が汎用メソッドであり、キャストするSubClassOne
またはSubClassTwo
のどちらがメソッドのジェネリック型パラメータに依存するので、単にSubClassOne
またはSubClassTwo
にキャストできません。
func castObj<T>(asType: T.Type) {
(self.obj as? T).prop
}
castObj(asType: SubClassOne.self)
またはcastObj(asType: SubClassTwo.self)
と呼ばれるものです。しかし、私たちは同じ問題に遭遇します:SubClassOne
とSubClassTwo
の両方を受け入れる定義できる唯一のジェネリック型パラメータの制約はAny
であり、SwiftコンパイラはValue of type 'T' has no member 'prop'
という文句を言います。 Iは所望の特性をカプセル化プロトコルを定義しようとした回避策として
:
protocol HasProp {
var prop: SomeBaseClass { get }
}
そしてIはSubClassOne
とSubClassTwo
の宣言にこれを追加しました。しかし、これはさらに別のエラーが発生しました:Type 'SubClassOne' does not conform to protocol 'HasProp'
。 SubClassOne
とSubClassTwo
の両方がprop
からBaseClass<SomeSubClass>
に継承されているので、実際にはプロトコルに準拠しているので、私も混乱します。要約すると
:
- が
BaseClass
のプロパティへのアクセスを提供し、より具体的なタイプでSubClassOne
とSubClassTwo
のインスタンスを格納することが可能ですか?そうでない場合、なぜですか? - なぜサブクラスはプロトコルに準拠していないのですか?
- 希望の動作を達成するためにデザインを変更するにはどうすればよいですか?
私もこれを試してみました。最初に 'obj'の型を定義しようとしたときと同じ問題が発生しました。 'BaseClass'の型制約はうまくいきません。' genericClass 'には' 'の引数が必要です。例えば、 'BaseClass'のようにしようとすると、私は '' SubClassOne.Type '型の値を' BaseClass .Type''型に変換することができません。 'castObj(asType:SubClassOne.self)' –
asaini007
この関数は 'BaseClass'の内部かその外側に定義されていますか? –
それは外に定義されています – asaini007