CodeGym/Java Blog/ランダム/Javaの抽象クラスの具体例
John Squirrels
レベル 41
San Francisco

Javaの抽象クラスの具体例

ランダム グループに公開済み
人のメンバー
やあ!これまでのレッスンでは、インターフェースに出会い、その用途を理解しました。今日のトピックは前回のトピックを繰り返します。Java の 抽象クラスについて話しましょう。Javaの抽象クラスの具体例 - 1

クラスが「抽象」と呼ばれる理由

おそらく「抽象化」とは何かを覚えているでしょう。それについてはすでに説明しました。:) 忘れてしまっても心配しないでください。覚えておいてください: クラスを設計してオブジェクトを作成するときは、エンティティの主要なプロパティのみを識別し、マイナーなプロパティは破棄する必要があるというOOP の原則です。たとえば、SchoolTeacherクラスを設計している場合、「height」プロパティはほとんど必要ありません。実際、この特性は教師にとっては無関係です。しかし、クラスを作成する場合BasketballPlayer、成長は重要な特性になります。それで聞いてください。抽象クラスこれは抽象的なものであり、将来のクラスのグループにとって未完成の「空白」です。ブランクはそのままでは使用できません。それはあまりにも「生」すぎます。ただし、これは、抽象クラスを継承する将来のクラスが持つ特定の状態と一般的な動作を記述します。

抽象 Java クラスの例

車の簡単な例を考えてみましょう。
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public abstract void gas();

   public abstract void brake();

   public String getModel() {
       return model;
   }

   public void setModel(String model) {
       this.model = model;
   }

   public String getColor() {
       return color;
   }

   public void setColor(String color) {
       this.color = color;
   }

   public int getMaxSpeed() {
       return maxSpeed;
   }

   public void setMaxSpeed(int maxSpeed) {
       this.maxSpeed = maxSpeed;
   }
}
最も単純な抽象クラスは次のようになります。ご覧のとおり、これは特別なことではありません:) なぜそれが必要なのでしょうか? まず第一に、必要なエンティティである車を可能な限り最も抽象的な方法で説明します。「abstract」という言葉を使用しているのには理由があります。現実の世界には「抽象的な車」は存在しません。トラック、レースカー、セダン、クーペ、SUV があります。 私たちの抽象クラスは、後で車のクラスを作成するために使用する単なる「青写真」です。
public class Sedan extends Car {

   @Override
   public void gas() {
       System.out.println("The sedan is accelerating!");
   }

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}
これは、継承に関するレッスンで説明したことと非常によく似ています。しかし、それらのレッスンでは Car クラスがあり、そのメソッドは抽象的ではありませんでした。しかし、この解決策には多くの欠点があり、それらは抽象クラスで修正されています。何よりもまず、抽象クラスのインスタンスを作成することはできません
public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Error! The Car class is abstract!
   }
}
Java の作成者は、この「機能」を特別に設計しました。もう一度注意してください:抽象クラスは、将来の「通常の」クラスの単なる青写真です。設計図のコピーは必要ありませんね? そして、抽象クラスのインスタンスは作成しません:) しかし、Carクラスが抽象クラスでない場合は、そのインスタンスを簡単に作成できます。
public class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       // Some logic
   }

    public void brake() {
       // Some logic
   }
}


public class Main {

   public static void main(String[] args) {

       Car car = new Car(); // Everything is fine. A car is created.
   }
}
さて、私たちのプログラムには、ある種の理解できない車が登場します。それはトラックでも、レースカーでも、セダンでもなく、それが何であるかはまったく不明です。まさに自然界には存在しない「抽象的なクルマ」です。動物を使って同じ例を提供できます。Animalクラス (抽象動物)を想像してください。それがどのような動物で、どの科に属し、どのような特徴を持っているのかは不明です。あなたのプログラムでそれが見られるのは奇妙です。自然界には「抽象的な動物」は存在しません。犬、猫、キツネ、モグラなどの抽象クラスだけが、私たちに抽象オブジェクトを提供します。これらは私たちに基本的な状態と動作を与えます。たとえば、すべての車にはモデル最高速度があり、次の条件を適用できる必要があります。ガソリンブレーキ。それでおしまい。これは一般的な抽象的な計画です。次に、必要なクラスを設計します。 注:抽象クラスの 2 つのメソッドもabstractとして指定されており、実装はありません。理由は同じです。抽象クラスは抽象自動車のデフォルトの動作を作成しません。それらはすべての車ができるべきことを示しているだけです。ただし、デフォルトの動作が必要な場合は、抽象クラスにメソッドを実装できます。Java ではこれを禁止していません。
public abstract class Car {

   private String model;
   private String color;
   private int maxSpeed;

   public void gas() {
       System.out.println("Gas!");
   }

   public abstract void brake();

   // Getters and setters
}


public class Sedan extends Car {

   @Override
   public void brake() {
       System.out.println("The sedan is slowing down!");
   }

}

public class Main {

   public static void main(String[] args) {

       Sedan sedan = new Sedan();
       sedan.gas();
   }
}
コンソール出力: 「Gas!」 ご覧のとおり、抽象クラスに最初のメソッドを実装しましたが、2 番目のメソッドは実装しませんでした。その結果、クラスSedanの動作は 2 つの部分に分割されます。メソッドを呼び出す場合gas()、呼び出し抽象親クラスまで「上昇」しますCarが、クラスbrake()内のメソッドをオーバーライドSedanしました。これは非常に便利で柔軟であることがわかりました。しかし、今のクラスはそれほど抽象的ではありません。結局のところ、そのメソッドの半分は実装されています。これは実際には非常に重要な機能です -クラスのメソッドの少なくとも 1 つが抽象である場合、クラスは抽象です。2 つの方法のうちの 1 つ、または 1,000 の方法のうちの少なくとも 1 つでは、違いはありません。すべてのメソッドを実装し、抽象化したままにすることもできます。その場合、それは抽象メソッドのない抽象クラスになります。原則として、これは可能であり、コンパイラはエラーを生成しませんが、それは避けたほうがよいでしょう。抽象という言葉はその意味を失い、仲間のプログラマーは非常に驚くでしょう :/ 同時に、メソッドがマークされている場合、 abstract という単語を使用する場合、各子クラスはそれを実装するか、abstract として宣言する必要があります。それ以外の場合、コンパイラはエラーを生成します。 もちろん、各クラスは 1 つの抽象クラスのみを継承できるため、継承に関しては抽象クラスと通常のクラスに違いはありません。抽象クラスを継承するか通常のクラスを継承するかは関係なく、親クラスは 1 つだけ存在できます。

Java にクラスの多重継承がない理由

Java には多重継承がないことはすでに述べましたが、その理由についてはまだ詳しく調べていません。今度はそれをやってみましょう。実際のところ、Java に複数の継承がある場合、子クラスはどの特定の動作を選択するかを決定できません。2 つのクラスがあるとします。 —ToasterNuclearBomb:
public class Toaster {


 public void on() {

       System.out.println("The toaster is on. Toast is being prepared!");
   }

   public void off() {

       System.out.println("The toaster is off!");
   }
}


public class NuclearBomb {

   public void on() {

       System.out.println("Boom!");
   }
}
ご覧のとおり、どちらにもon()メソッドがあります。トースターの場合は焼き始めます。核爆弾の場合、爆発を引き起こします。おっと: / ここで、その中間にあるものを作成しようと決めたと想像してください (理由は聞かないでください!)。これでMysteriousDeviceクラスが完成しました。 もちろん、このコードは機能しません。「ただし、機能する可能性がある」例としてのみ提供します。
public class MysteriousDevice extends Toaster, NuclearBomb {

   public static void main(String[] args) {

       MysteriousDevice mysteriousDevice = new MysteriousDevice();
       mysteriousDevice.on(); // So what should happen here? Do we get toast or a nuclear apocalypse?
   }
}
私たちが持っているものを見てみましょう。謎の装置はトースターと核爆弾を同時に継承している。どちらにもメソッドがありますon()。その結果、on()メソッドを呼び出す場合、オブジェクトに対してどのメソッドを呼び出す必要があるかが不明確になりますMysteriousDevice。オブジェクトがそれを知ることはできません。さらに言えば、NuclearBomb にはoff()メソッドがないため、推測が正しくなければ、デバイスを無効にすることは不可能になります。 Java の抽象クラスの具体例 - 2オブジェクトがどのような動作を示すかわからないというこの「混乱」のため、Java の作成者は多重継承を放棄しました。ただし、Java クラスは複数のインターフェイスを実装できることを思い出してください。 ところで、学習の中で、少なくとも 1 つの抽象クラスに遭遇したことがあるはずです。
public abstract class Calendar implements Serializable, Cloneable, Comparable<Calendar>
それはあなたの古い友人、Calendarクラスです。それは抽象的であり、複数の子を持ちます。そのうちの 1 つは ですGregorianCalendar。日付に関するレッスンですでに使用しました。:) すべてが十分に明確に見えます。質問が 1 つだけあります。そもそも、抽象クラスとインターフェイスの根本的な違いは何でしょうか? なぜ言語を 1 つに限定するのではなく、両方を Java に追加したのでしょうか? 結局のところ、それで十分だったでしょう。これについては次のレッスンで説明します。それまで :)
コメント
  • 人気
  • 新規
  • 古い
コメントを残すには、サインインしている必要があります
このページにはまだコメントがありません