Java の新しいバージョンはそれぞれ、以前のバージョンとは異なります。これまで取り上げてきた内容からのこのような変更の例として、この言語には
同様に、Java 8 は Java 7 とは著しく異なります。もちろん、重要な革新を無視するつもりはありません。このレッスンではインターフェースについて話しているので、言語への 1 つの更新、インターフェースのデフォルト・メソッドについて考えてみましょう。インターフェースが動作を実装していないことはすでにご存知でしょう。その目的は、インターフェイスを実装するすべてのオブジェクトにどのような動作が存在する必要があるかを記述することです。しかし、開発者は、メソッドの実装がすべてのクラスで同じであるという状況に頻繁に遭遇しました。古い車の例を見てみましょう。
enums
Java 5 より前には存在しなかったものがあります。
public interface Car {
public void gas();
public void brake();
}
public class Sedan implements Car {
@Override
public void gas() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class Truck implements Car {
@Override
public void go() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
public class F1Car implements Car {
@Override
public void go() {
System.out.println("Gas!");
}
@Override
public void brake() {
System.out.println("Brake!");
}
}
このコードの主な問題は何だと思いますか? おそらく、重複したコードをたくさん書いたことに気づいたでしょう。これはプログラミングでよくある問題であり、回避する必要があります。Java 8 のリリース前には特別な解決策がなかったことは別の問題です。Java 8 のバージョンが登場すると、デフォルトのメソッドを定義し、それをインターフェース内に直接実装できるようになりました。その方法は次のとおりです。
public interface Car {
public default void gas() {
System.out.println("Gas!");
}
public default void brake() {
System.out.println("Brake!");
}
}
public class Sedan implements Car {
}
public class Truck implements Car {
}
public class F1Car implements Car {
}
すべての車で同じだったメソッドgas()
とbrake()
メソッドがインターフェイスに移動され、重複したコードが必要なくなりました。そしてメソッドは各クラスで利用可能です。
public class Main {
public static void main(String[] args) {
F1Car f1Car = new F1Car();
Sedan sedan = new Sedan();
Truck truck = new Truck();
truck.gas();
sedan.gas();
f1Car.brake();
}
}
メソッドを持つクラスが 100 個ありgas()
、そのうちの 99 個だけが同じ動作をする必要がある場合はどうなるでしょうか? それはすべてを台無しにしてしまいますか?この場合、デフォルトの方法は機能しないでしょうか? もちろんそうではありません:) デフォルトのインターフェースメソッドはオーバーライドできます。
public class UnusualCar implements Car {
@Override
public void go() {
System.out.println("This car accelerates differently!");
}
@Override
public void brake() {
System.out.println("This car slows down differently!");
}
}
他の 99 タイプの車はすべてデフォルトの方法を採用しますが、UnusualCar
クラスは例外です。全体像を損なうことなく、冷静に自らの行動を定義します。インターフェイスでの多重継承。すでにご存知のとおり、Java には多重継承はありません。これには多くの理由があります。これらについては、別のレッスンで詳しく検討します。C++ などの他の言語では、状況は逆になります。同じオブジェクトがいくつかの異なる特性や動作を持つ可能性があるため、多重継承は深刻な問題を引き起こしません。たとえば、私たちは両親にとっては子供であり、教師にとっては生徒であり、医師にとっては患者です。実生活では、私たちはさまざまな役割を果たしており、それに応じて異なる行動をとります。明らかに、私たちは教師に対して、親しい友人に対してとは異なる方法で接します。この状況をコードに変換してみましょう。Pond と Aviary という 2 つのクラスがあると想像してみましょう。池には泳ぐ鳥が必要ですが、鳥小屋には飛ぶ鳥が必要です。これを表すために、次の 2 つの基本クラスを作成しました。FlyingBird
そしてWaterfowl
。
public class Waterfowl {
}
public class FlyingBird {
}
FlyingBird
したがって、継承する鳥は鳥小屋に 送り、派生する鳥はWaterfowl
池に行きます。すべてが単純明快に思えます。しかし、どこかでアヒルを定義する必要がある場合はどうすればよいでしょうか? アヒルは泳ぐことも飛ぶこともできます。しかし、多重継承はありません。幸いなことに、Java はインターフェースの複数の実装をサポートしています。クラスが複数の親を継承できない場合、複数のインターフェイスを実装するのは簡単です。私たちのアヒルは、泳ぐ鳥だけでなく飛ぶ鳥にもなります :) 望ましい結果を達成するために必要なのは、クラスではなくインターフェイスを FlyingBird
作成することだけです。Waterfowl
public class Duck implements FlyingBird, Waterfowl {
// Methods of both interfaces combine easily into one class
@Override
public void fly() {
System.out.println("Flying!");
}
@Override
public void swim() {
System.out.println("Swimming!");
}
}
これは、私たちのプログラムが柔軟なクラス管理能力を保持していることを意味します。これをデフォルトのメソッドと組み合わせると、オブジェクトの動作を決定する能力はほぼ無限になります。:)
GO TO FULL VERSION