7

ご挨拶。私は次のクラスを持っています:

public class Ship
{
    public enum ValidShips
    {
        Minesweeper,
        Cruiser,
        Destroyer,
        Submarine,
        AircraftCarrier
    }

    public enum ShipOrientation
    {
        North,
        East,
        South,
        West
    }

    public enum ShipStatus
    {
        Floating,
        Destroyed
    }

    public ValidShips shipType { get; set; }

    public ShipUnit[] shipUnit { get; set; }

    public ShipOrientation shipOrientation { get; set; }

    public ShipStatus shipStatus { get; set; }

    public Ship(ValidShips ShipType, int unitLength)
    {
        shipStatus = ShipStatus.Floating;

        shipType = ShipType;

        shipUnit = new ShipUnit[unitLength];

        for (int i = 0; i < unitLength; i++)
        {
            shipUnit[i] = new ShipUnit();
        }
    }
}

私はこのクラスを次のように継承したいと思います:

public class ShipPlacementArray : Ship
{

}

意味あり。

私が知りたいのは、基本クラスの特定の機能を削除する方法です。

例えば:

    public ShipUnit[] shipUnit { get; set; } // from base class

私はそれが欲しい:

    public ShipUnit[][] shipUnit { get; set; } // in the derived class

私の質問は、基本クラスの shipUnit を完全に隠すコードをどのように実装するのですか?

そうしないと、派生クラスに 2 つの shipUnit 実装が作成されます。

お時間をいただきありがとうございます。

ShipPlacementArray は 1 つの船のみを扱います。ただし、配列は船を配置できる方向を反映しています。

4

11 に答える 11

15

私が知りたいのは、基本クラスの特定の機能を削除する方法です。

あなたはそうしない。これは継承のポイントではありません。継承のポイントは、基本クラスの機能をすべて継承し、追加/変更することです。これは「is-a」関係用です。たとえば、「車乗り物です」などです。

私の質問は、基本クラスの shipUnit を完全に隠すコードをどのように実装するのですか?

複数のオブジェクトShipPlacementArrayのラッパーまたはコンテナーになりたいようです。Shipこれは、継承を使用する必要がある場合とは思えません。

ShipPlacementArray「aは の一種Shipですか?」という質問を自問してください。

于 2010-02-22T14:50:13.970 に答える
7

私の経験では、継承されたクラスのクラスからプロパティを削除するたびに、クラスの設計に欠陥がありました。この問題を解決する 1 つの方法は、ShipUnit プロパティを指定せずに新しい基本クラスを作成し、その基本クラスを 2 回継承することです。どちらのサブクラスでも、必要に応じて ShipUnit を実装できます。

于 2010-02-22T14:53:47.273 に答える
2

派生クラスで基底クラスのメンバーを非表示にすることはできません。特定のインスタンスでは、派生クラスの非表示メンバーでキーワードを使用して基本メンバーをマスクまたは非表示newにすることができますが、ユーザーはいつでもオブジェクトを基本クラスにキャストして(base)instance_of_derived、基本クラスのメンバーにアクセスできます。

したがって、たとえば、派生クラスで次のことができます。

public new ShipUnit[][] shipUnit { get; set; }

しかし、私はできる:

((Ship)ShipPlacementArray_instance).shipUnit

そして、これは元の shipUnit を参照します。したがって、メンバーを「非表示」にすることはできますが、その機能やアクセシビリティを無効にすることはできません。

于 2010-02-22T14:49:52.103 に答える
2

C# の新しい修飾子を使用すると、継承されたメンバーを基底クラスのメンバーから隠すことができます。参考までにこちらのページをご覧ください。

于 2010-02-22T14:51:35.887 に答える
1

これが単に不自然な例なのか、それとも実際の問題なのかはわかりません。しかし、この場合の継承は望ましくないと思います。Ship と ShipPlacementArray があります。最後の「配列」は、配列データ型のように聞こえます。それを取り除くと、ShipPlacement ができます。

それはどこかの場所のように聞こえるので、Ship クラスのメンバーである必要がありますか?

于 2010-02-22T17:18:02.203 に答える
1

他の優れた回答に加えて、余談ですが、カプセル化がより良い選択肢であると思うかもしれません。多くの場合、最初はクラスから継承したいと考えていましたが、後で本当にそれをカプセル化したいことに気付きました。これを行うには、プライベート フィールドで元のクラスの新しいインスタンスを宣言するだけです。次に、以下のように元のクラスを呼び出すだけのパブリック プロパティと関数を作成し、公開される内容をきめ細かく制御します。これは、複雑さが増したり、(正当な理由で) 多重継承を実行できないなど、継承の欠点を回避する方法でもあります。

class SomeNew
{
  private SomeOld someOld = new SomeOld();//could have done this in constructor instead

  public DoSomething()
  {
    someOld.DoSomething();
  }
}
于 2010-02-22T14:56:28.943 に答える
1

「クラスの継承よりもオブジェクトの構成を優先する」-基本クラスから新しい動作を探している場合、それらは異なる型であるため、とにかく継承したくないようです。おそらく、Ship と ShipPlacementArray は共通のインターフェイスを継承する必要がありますが、共通の基本クラスから継承する必要はありません。使用する必要がある場所ならどこでもインターフェイスを使用できますが、ShipUnit マトリックスが必要な場合は、ShipPlacementArray タイプを明示的に使用します。

于 2010-02-23T03:31:53.703 に答える
0

new次のようにキーワードを使用できます。

public new ShipUnit[][] shipUnit { get; set; }
于 2010-02-22T14:50:25.017 に答える
0

new キーワードを使用するか、基本クラスの宣言に virtual を追加して、派生クラスでオーバーライドすることができます。

于 2010-02-23T09:19:47.547 に答える
0

「new」演算子を使用できます。のように

public new ShipUnit[][] shipUnit { get; set; } // in the derived class
于 2010-02-22T14:49:13.740 に答える
0

継承で何をモデル化したいのか完全には理解できませんが、それが間違ったツールであることは確かです。集約または構成が必要なものだと思います。

于 2010-02-22T14:55:21.980 に答える