1

Aタイプがのインスタンス変数を持つクラスがありますX

@interface A : NSObject {
    X *x;
}
@end

一部のXインスタンスは、さらにプロトコルに準拠していますPAこれらのXインスタンス専用のの専用バージョンを実装したいと思います。

@interface B : A {
    X <P> *x;
}
@end

これは正常にコンパイルされます。xただし、インスタンスからアクセスするBと、変更はに伝播されませんA。したがって、A再定義されていない関数はX、の関数以外のインスタンスを使用しますB

  • プロトコルのみが追加されたときに、インスタンス変数を再定義することはどういうわけか可能ですか?サブクラスについて も同様の質問があります。ただし、サブクラスとプロトコルは同じではありません。私のアプローチはうまくコンパイルされますが、意図したとおりに機能しません。

  • それが不可能な場合:これを実行するための一般的なパターンはありますか?

    1. インスタンス変数を新しいタイプでオーバーライドしないと、コードは醜いもので雑然とします。

      [((X <P> *)x) methodOfP]
      
    2. インスタンス変数をオーバーライドする場合は、変更を自分でスーパークラスに伝播する必要がありますA。これには追加の機能が必要です。

    3. インスタンス変数の代わりにプロパティを使用する:これでもうまくいくでしょうか?サブクラスでプロパティを再定義できますか?

      @interface A : NSObject {
          X *x;
      }
      @property (strong, nonatomic) X *x;
      @end
      @implementation A
      - (X *)x
      {
          return x;
      }
      - (void)setX:(X *)anX
      {
          x = anX;
      }
      @end
      
      @interface B : A
      @property (strong, nonatomic) X <P> *x;
      @end
      @implementation B
      @end
      
4

2 に答える 2

1

あなたがやろうとしていることは、オブジェクト指向プログラミングの基本原則であるLiskov Substitution Principleに違反しています。B のインスタンスは、A を期待する任意のコードに渡すことができ、そのコードはそれを A として処理する資格があります。つまり、オブジェクトがプロトコルに準拠しているという要件なし-setX:に、X のインスタンスを渡すことで、オブジェクトを呼び出すことができます。 P. _

つまり、A ではない A のサブクラスを作成しようとしています。

これを行いたいという事実は、設計上の混乱を示唆しています。一歩下がって考え直すべきです。まず、すべてのクラスをそのインターフェイスの観点からのみ設計し、それらのインターフェイスが継承の観点から理にかなっていることを確認します。その後、実装を検討してください。

于 2012-06-06T13:51:24.703 に答える
0

最も簡単な解決策は、インスタンス変数を非表示にすることです。これを行うには、ivar をインターフェイスから実装ファイル内のクラス継続に移動します。

@interface A ()
{
    X *x;
}
@end

または実装の先頭に:

@implementation A 
{
    X *x;
}
//methods go here
@end

のスーパークラス ivar に直接アクセスしないでください。代わりに を使用しますsuper.propertyNamex次に、プロトコルを実装する場合にのみ返すメソッドをサブクラスに追加できます。

-(X*<protocol>)xThatImplementProtocol
{
     X *x = super.x;

    return ([x conformsToProtocol:protocol]) ? x : nil;
}

ただし、この方法ではポリモーフィズムが壊れます。

正直なところ、この問題を解決するために、別のアプローチ、構成を使用していると思います。サブクラス化は自然にフィットするようには思えません。

于 2012-06-06T11:53:22.553 に答える