6

クラス A と B があります。今度は、A と B の両方でいくつかのフィールドとメソッドを使用する新しいクラス C を作成する必要がありますが、それらのすべてではありません。(私はAとBのものの約50%を使用します).

現在、A と B の両方から継承することを考えています。しかし、そうすると、C には意味のないフィールドやメソッドがたくさん含まれることになります。

基本的に、継承はコードを再利用する目的でのみ使用しています。そうしないと、A と B から多くのコード行をコピーして貼り付ける必要があります。

この習慣は本当に悪いですか?別のアプローチはありますか?

ありがとう!

4

5 に答える 5

6

継承には「半分である」という概念がないため、ここでの方法は絶対にありません。それは作曲の主要なケースのように聞こえます。

それぞれAB半分でC.

これがあなたのケースに当てはまるかどうかはわかりませんが、 A を 2 つの部分に分割し、 in に必要な機能を備えていることA1を検討してください。次に、intoとについても同じことを行います。A2CA1BB1B2

Aは と の合成でA1ありA2Bは と の合成でB1ありB2、はとCの合成です。不要な機能やデータを備えたものはありません。A1B1

于 2012-09-26T21:25:57.640 に答える
3

継承では、「isa」パラダイムを使用する必要があります。
ある種のAとBの
場合、CはA、Bから継承する必要があることを意味します。すでに多重継承を使用している場合は、AとBをそれぞれコードの小さなフラグメントを処理する複数のクラスに分割してから、必要なものからのみCを継承します-このように、Cは必要なスペースのみを占有します(AとBに多くのメンバーがあると仮定します)。
クラスのサイズはメンバーメソッドの影響を受けず、メンバーデータのみの影響を受けることに注意してください。

于 2012-09-26T21:12:36.483 に答える
3

Herb Sutter と Andrei Alexandrescu が著書C++ Coding Standards (item 34)friendで説明しているように、継承は、C++ を使用して 2 つのクラス間で使用できる最も緊密な関係の 1 つであり、クラス間の関係に次ぐものです。

OOの SOLID 原則によると、成功する設計はクラス間の疎結合を目指す必要があります。これは、依存関係を最小限に保つことを意味します。これは、継承が注意して使用する必要があるツールであることを意味します。

もちろん、通常、依存関係はどこかinterfaceに存在する必要があるため、実装をまったく行わないクラスから継承することも妥当な妥協案です ( C# や Java などの言語でのいわゆるs に似ています)。例えば

class IDriveable
{
public:
    virtual void GoForward() = 0;
    virtual void GoBackward() = 0;
};

class Car : public IDriveable { /* etc. */ };
class Bus : public IDriveable { /* etc. */ };
class Train : public IDriveable { /* etc. */ };

このアプローチでは、複数のDrivableクラス間で再利用されるコードの要素がある場合、通常、構成またはその他の弱い関係を使用して、繰り返されるコードを排除します。たとえば、 aと aの
コードを再利用したいが、左に回すのが非論理的である a ではなく、 andのメンバーである別のクラスになる可能性があります。TurnLeftBusCarTrainTurnLeftBusCar

  • さらに、あいまいに関連するすべてのクラスについて知る必要がある機能は、クラス階層の外部にあり、核心的な実装の詳細ではなく、インターフェイス/ベースのみを認識します。

最終的には、合成用の少量の余分なコードが追加される可能性がありますが、多くの場合、設計はそれほど複雑ではなく、通常は管理が容易になります。このようなコードを設計するための厳格なルールはありません。これは、解決しようとしている固有の問題に完全に依存するためです。

密結合なしでコードを再利用する方法は他にもあります。テンプレートを使用すると、純粋なvirtual関数を含む空のクラスを使用せずにインターフェイスを暗黙的に定義できます (テンプレートは追加の型安全性を提供します。これは非常に良いことですが、構文的にはもう少し複雑です)。

std::functionそして、より機能的なスタイルでコードを再利用するためにラムダを使用できる方法があります。通常、関数オブジェクトを渡すときに密接な依存関係は関係ありません。

于 2012-09-26T21:32:58.290 に答える
2

悪いです。論理的に理にかなっている場合にのみ、継承を使用してください。

代わりにコンポジションを使用してください (private継承はコンポジションの一種ですが、昔ながらの方法を使用することをお勧めします):

class C
{
    A a;
    B b;
}

がとCで構成されていない場合は、代わりにポインターを保持することもできるため、 のサイズは増加しません。ABC

于 2012-09-26T21:09:30.940 に答える
0

コードをリファクタリングすることでメリットが得られるようです。

これの代わりに:

class A
{
  virtual void foo();
  virtual void bar();
};

class B
{
  virtual void biz();
  virtual void baz();
};

class C : public A, public B
{
  virtual void foo() { /* my stuff */ }
  virtual void biz() { /* my other stuff */ +

  // but I don't need bar or baz!
};

C で必要な A と B の概念的に異なる部分を分割することを検討してください。

class core_A
{
  virtual void foo();
};

class A : public core_A
{
  virtual void bar();
};

class core_B
{
  virtual void biz();
};

class B : public core_B
{
  virtual void baz();
};

class C : public core_A, public core_B
{
  virtual void foo() { /* my stuff */ }
  virtual void biz() { /* my other stuff */ +

  // Great, I don't have bar or baz!
};
于 2012-09-26T22:37:44.220 に答える