web-dev-qa-db-ja.com

抽象クラスと抽象メソッドとは何ですか?

私はいくつかの説明を得ましたが、これまでのところ、Javaの抽象クラスと抽象メソッドが何であるかを理解できません。プログラムのセキュリティで何かをしなければならないと言う人もいれば、そのようなことではないと言っている人もいます。 Dietel&Dietelの本でさえ、目的がわからない。いつ、どこで、なぜ使用するのですか?

5
Umer Hassan

まず最初に、サンプルはC#で作成されます。しかし、あなたはそれを理解するのに問題はないと思います。そう...

抽象クラスのオブジェクトをインスタンス化することはできません。インスタンス化する場合は、クラスから派生するサブクラスが必要です。ただし、これは以前に遭遇したことがあるので、おそらく役に立たないでしょう。

それでは、例を試してみましょう。

あなたが体重を減らしたいと考え、栄養士があなたの食物摂取量を追跡するように頼んだとします。あなたが再び彼女に行くとき、あなたは彼女にあなたが「食べ物」を食べたと言うことができません。それは間違いではありませんが、すべての食べ物にはカロリーがあるので、彼女には「抽象的」過ぎます。だからあなたは彼女にどの食べ物を伝える必要があります。

それで、もし彼女がそれをコード化するなら...彼女は抽象クラスFoodを持っているでしょう。

abstract class Food
{
    public int CaloriesPerPound { get; set; }
    //...
}

どうして? 「私は食べ物を食べた」とは言えないからです。

{
    Food fries = new Food(); //This won't even compile
}

したがって、具体的なクラスが必要です:

class Fruit : Food
{
 //Other stuff related only to fruits
}

class Bread : Food
{ 
 //Other stuff related only to Bread
}

それで、あなたはそれがどんな食べ物であるか正確に言わなければならないでしょう。

{
   Apple desert = new Apple(); //Now we are talking
}

しかし、彼女はまだ食品クラスを必要としています、それは彼女にとってまだ興味深いです:

class Meal
{
    public List<Food> Foods { get; set; }
    //Other meal related stuff
    public int TotalCalories()
    {
        int calories = 0;
        foreach (Food food in Foods)
        {
            calories = calories + food.CaloriesPerPound * FoodQuantity;
        }
        return calories;
    }
}

これは、抽象クラスが必要な場合の例です。基本クラスが必要だが、クラスのオブジェクトを誰も作成したくない場合。

抽象CANには抽象メソッドがあります。必要はありません。抽象メソッドのない抽象クラスがあってもまったく問題ありません。そういえば...

抽象メソッドは広すぎるものです。動作に類似点はないため、抽象メソッドを持つクラスから派生したクラスは、スーパークラスの実装を呼び出すことができません。また、すべてのサブクラスに、そのメソッドのバージョンを実装するように強制しています。

別の例を試してみましょうか?動物バンドシミュレーター。あなたは動物を飼っていて、それぞれが音を立てるでしょう。しかし、これらはまったく異なる「実装」であり、共通点はありません。犬は猫、象の猫、クリケットの象とは異なります。したがって、抽象メソッドMakeSoundがあります。

class Animal
{
    public abstract void MakeSound();
}

ただし、クラスに抽象メソッドがある場合は、クラス全体が抽象化されます。

abstract class Animal
{
    public abstract void MakeSound();
}

したがって、残りのコードは次のようになります。

class Dog : Animal
{
    public void MakeSound()
    {
        //bark at the moon
    }
}

class Cat : Animal
{
    public void MakeSound()
    {
        //meowing for food
    }
}

そしてバンド!

class AnimalBand
{
    public List<Animal> Animals { get; set; }
    public void RockOn()
    {
        foreach (Animal animal in Animals)
        {
            animal.MakeSound();
        }
    }
}

したがって、これは抽象メソッドを使用する場合の例です。

これが本質だと思います。それは少し強制的/複雑であるかもしれませんが、それは全体的に要点を理解していると思います。以前は役に立たなかった例に戻り、それらが今意味をなしているかどうかを確認してください。

私は手足を出して、あなたは初心者だと言います。これは奇妙に思えるかもしれませんし、抽象クラスを使用しても何のメリットもないかもしれません。

大丈夫です。私たちが始めたとき、それはほとんどすべての人にとって奇妙です。しかし、やがて、あなたはそれを理解することを学ぶでしょう。

16
Luiz Angelo

抽象クラスは、インスタンス化できないクラスです(つまり、new myAbstractClass())。 inherit の他のクラスのテンプレートとして使用されます。

抽象メソッドは、派生クラスでオーバーライド(つまり、実装)できる抽象クラスのメソッドです。

interfaceabstractclassの違いは、派生クラスで利用できる抽象クラス(つまり、通常のメソッドまたは仮想メソッド)に機能を配置できることです。一方、インターフェースは空のテンプレートです。

5
Robert Harvey

抽象クラスを使用すると、他のクラスを拡張するためのスケルトンを作成できます。

それらをインスタンス化することはできませんが、それらを拡張するクラスで使用できるいくつかの一般的な実装を置くことができます。

2
Atropo

抽象クラスは、1つ以上の具象(抽象ではない)クラスで使用されるいくつかの一般的な機能を実装するクラスです。

これの良い例は、Javaの AbstractList クラスです。このクラスは、ArrayList(具象クラス)および AbstractSequentialListLinkedListによって拡張される抽象クラス)によって拡張されます。

AbstractListをインスタンス化することは決してないでしょう(どれが欲しいですか?ArrayList?Vector?LinkedList?)したがって、これを防ぐために抽象化されています。ただし、リストの機能に必要ないくつかの内部機能(フェイルファーストの変更カウント)を実装しています。

抽象メソッドは、抽象クラスまたはインターフェイスに実装されていないが、具象クラスに実装する必要があるメソッドです。

メソッドを抽象化したい主な理由は、パブリックAPIの一部であることです。 compareToComparableメソッドが抽象的である場合-他のクラスが呼び出すためにこれを正しく実装する方法を知っているのは具象クラスだけです。

2
user40980

抽象クラス/メソッドは、概念的には、具体的な実装の「出発点」です。

抽象メソッドまたは他のメンバーは、コードを持つことができません。これは、文字通り、抽象ベースから派生したクラスによって実装されなければならないメンバーのプレースホルダーです。これはインターフェースのメソッド宣言に似ていますが、抽象クラスはパブリックだけでなく、継承可能な可視性の抽象メンバーを定義できます。その抽象メンバーは、抽象クラスの任意のコードで使用にすることができます。通常、その目的は、派生クラスが実装固有のロジックまたは動作を指定できるようにすることです。周囲のコードからの抽出により、残りのコードは実装に依存しなくなります。

抽象クラスはインスタンス化できません。これは、この点でのインターフェースと同様に、メンバーとパラメーターの共通型から派生して使用されるために存在します。抽象メンバーを持つクラスは、それ自体が抽象としてマークされている必要がありますが、抽象メンバーのないクラスも抽象としてマークできます。したがって、抽象クラスは非抽象メンバーにコードを含めることができます。これは、インターフェースとの主な違いです(他の重要な違いは、「パブリック」よりも見えにくい抽象メンバーを定義できることです)。これは、抽象クラスの実装間で共通のコードを共有(したがって再利用)するための一般的な戦術です。

それらを使用する場合、簡潔に言えば、通常インターフェイスを使用する場合はいつでも、抽象クラスを使用しますが、ベースの派生実装間で共有できるコードも定義したい場合。

同じ継承階層でインターフェイスと抽象を組み合わせるかどうかに関して、JavaとC#の間で異なるベストプラクティスがあります。命名規則により、単一の抽象クラスによって直接実装されたインターフェースがJavaで冗長になるのは私の経験です(インターフェース名はクラス名のように見えるはずなので、プログラマーは何に注意する必要はありません使用)。 C#では、パターンは少し「深い」と見なされますが、インターフェイスは慣例により「I-」で始まるため、より受け入れられます。どちらの方法でも、配置により、抽象クラスでさえ、依存クラスに影響を与えることなくリファクタリングまたは置換できます。抽象DoerBaseの実装だけでなく、新しいBetterDoerBaseの実装を含むすべてのDoer(またはIDoer)、またはインターフェイスから直接継承する具象クラスを使用できます。

1
KeithS

抽象クラスの実際の例は、Humanなどです。しかし、Humanオブジェクトをインスタンス化しますか?番号! InfantChildのようなHuman抽象クラスからさらにクラスを派生します。 、大人 Womanなど。さらに、これらの派生クラスの元の動作を階層内で拡張/制限します。

0
Maxood