9

私は一種の研究開発を行っていましたが、抽象クラスの概念と混同しています。

抽象クラスについて私が知っていることは、それには具象メソッドが含まれている可能性があり、仮想メソッドが含まれている可能性があるということです。抽象メソッドが含まれる場合と含まれない場合があり、フィールドが含まれていて、インスタンスの直接作成が制限されている場合があります。

ただし、これらすべてを単純な基本クラスで実現できます (仮想メソッドの追加は、そこに実装を含まずオーバーライドする仮想メソッドを持つ基本クラスは抽象メソッドと同じであるため、多くのことを行います)。では、インターフェイスが複数の継承とイベントをサポートしているにもかかわらず、なぜ抽象クラスが必要なのでしょうか?

4

4 に答える 4

20

しかし、これらすべてを単純な基本クラスで実現できます

いいえ、できません。抽象メソッド (署名が定義されているが、実装が指定されていないため、派生クラスが実装を提供することを強制するメソッド) を持つ非抽象クラスを持つことはできません。

抽象クラスは、実装されたメソッドと抽象メソッドの組み合わせを提供できるように存在します。

abstract何もしない具体的な実装を使用して、クラスの使用を回避しようとすることもできますが、いくつかの欠点があります。

  • 呼び出し元が実装をオーバーライドすることを強制しません。
  • 実際には機能していないのに、特に型とそれらのメソッドが機能しているという印象を与えます。抽象メソッドと型の機能を追加することで、不完全であることを認識していない人による不完全な型の意図しない使用を防ぐことができます。
  • これは、サブクラスが提供する必要がある機能と、機能しているがオプションで拡張できる基本クラスのメソッドについて、サブクラスに明確な契約を提供します。

また、abstract のない世界で非 void メソッドを検討してください。それらは、スロー (つまりNotImplementedException) または無効な値 (つまりnull) を返す必要があります。これは、何もしないメソッドよりもはるかに悪い可能性があります。

于 2013-09-19T17:20:24.803 に答える
17

主な違いは、基本クラスをインスタンス化できるのに対し、コンパイラは抽象クラスをインスタンス化できないことです (これは意味がないかもしれません)。

AbstractType a = new AbstractType(); //compiler error
AbstractType d = new DerivedType(); //OK

BaseType b = new BaseType(); //OK

変数dを使用すると、抽象メソッドがオーバーライドされていることが保証されます (そうしないと、DerivedTypeクラスにコンパイラ エラーが発生します)。

あなたはまだ多くの混乱についてコメントしているので、私が実際にこの概念をクリックした例を挙げます。タワー ディフェンス ゲームを作成しているとします。タワー クラスがあり、すべてのタワーには攻撃する能力があるため、次のような抽象タワー クラスを作成します。

abstract class Tower
{
    abstract void Attack();
}

これで、いくつかのタワー クラスを作成できます。

class FlameTower : Tower
{
    override void Attack()
    {
        //Shoot flames at everyone
    }
}

class IceTower : Tower
{
    override void Attack()
    {
        //Shoot ice everywhere
    }
}

タワーのリストを宣言する場合は、次のように記述できます。

 List<Tower> towerList = new List<Tower>();
 towerList.Add(new FireTower());
 towerList.Add(new IceTower());

次に、それらを繰り返して、すべての攻撃を行います。

 foreach (Tower t in towerList)
 {
     t.Attack();
 }

また、すべてのクラスは抽象としてマークされているため、攻撃を実装していることが保証されており、実装していない場合はコンパイル エラーになります。基本クラスがこれを許可する場合を除いて、これはすべて基本クラスで実行できます。

 towerList.Add(new Tower());

これで attack を呼び出そうとするとnew Tower()、空の抽象メソッドにヒットしますが、これは私たちが望んでいるものではありません。したがって、何かをジェネリック タワーとして宣言することを禁止するために、クラスを抽象化します。そうすれば、すべてが独自の定義をAttack持ち、何かを実行することがわかります。

于 2013-09-19T17:16:52.390 に答える
3

1つの簡単な答えは次のとおりです。

基本クラスにはメソッドの独自の実装があり、これらの実装は継承されたクラスで使用/追加できます。基本クラスをインスタンス化できます

抽象クラスには、クラス メソッドの宣言があります。抽象クラスを継承するクラスは、その抽象メソッドを実装するか、それ自体を抽象化する必要があります。抽象クラスをインスタンス化できません

例:-

public abstract class A
{
   public void Method1()
   {
     //method code
   }

   public abstract void Method2();

   public virtual void Method3()
   {
    //method code for class A, when class A calls Method3, this code is executed
   }
}

public class B : A
{
   public override void Method2()
   {
     //this must be implemented here to use it
   }

   public override void Method3()
   {
     //method code for class B, when class B calls Method3, this code is executed
     //or, if you choose not to override this method, the compiler will use the code in class A
   }
}

クラス B は継承されているため、クラス A の Method1 を引き続き使用できます。また、クラス A を抽象化する場合は、すべてのメソッドを Method2 のように宣言し、使用できるようにクラス B に実装する必要があります。

于 2013-09-19T17:16:57.177 に答える