親クラスとその子を持つ次のコードがあります。ポリモーフィズムを使用することでコードがどのように利益を得るかを判断しようとしています。
_class FlyingMachines {
public void fly() {
System.out.println("No implementation");
}
}
class Jet extends FlyingMachines {
public void fly() {
System.out.println("Start, Taxi, Fly");
}
public void bombardment() {
System.out.println("Throw Missile");
}
}
public class PolymorphicTest {
public static void main(String[] args) {
FlyingMachines flm = new Jet();
flm.fly();
Jet j = new Jet();
j.bombardment();
j.fly();
}
}
_
flm.fly()
とj.fly()
の両方で同じ答えが得られる場合の多態性の利点は何ですか?
OOデザインを最初に見てみましょう。継承はIS-A関係を表します。通常、「FlyingMachines
を飛ばす」などと言うことができます。すべての特定のFlyingMachines
(サブクラス)IS-A FlyingMachines
(親クラス)、たとえばJet
は、この「FlyingMachines
フライを許可」に適合しますが、このフライングは実際にフライになります特定の関数(サブクラス)の機能、それがポリモーフィズムです。
したがって、抽象的な方法、指向のインターフェイス、および基本クラスで物事を行い、実際には詳細な実装に依存せず、ポリモーフィズムが正しいことを行います!
あなたの例では、FlyingMachine
のサブクラスが1つしかないため、ポリモーフィズムの使用はあまり役に立ちません。多型は、複数の種類のFlyingMachine
がある場合に役立ちます。次に、あらゆる種類のFlyingMachine
を受け入れ、そのfly()
メソッドを使用するメソッドを作成できます。例としては、testMaxAltitude(FlyingMachine)
があります。
ポリモーフィズムでのみ利用可能なもう1つの機能は、List<FlyingMachine>
を持ち、Jet
、Kite
、またはVerySmallPebbles
を格納する機能です。
ポリモーフィズムを使用するための最良のケースの1つは、実装ではなくインターフェイスを参照する機能です。
たとえば、List<FlyingMachine>
ではなくArrayList<FlyingMachine>
として返されるメソッドを使用することをお勧めします。そうすれば、メソッドを使用するコードを壊すことなく、メソッド内の実装をLinkedList
またはStack
に変更できます。
flm.fly()
とj.fly()
の両方で同じ答えが得られる場合の多態性の利点は何ですか?
利点は
_FlyingMachines flm = new Jet();
flm.fly();
_
返す
_"Start, Taxi, Fly"
_
の代わりに
_"No implementation"
_
それがポリモーフィズムです。タイプFlyingMachine
のオブジェクトでfly()
を呼び出しますが、実際にはJet
であることがわかっており、代わりに適切なfly()
メソッドを呼び出します_"No implementation"
_を出力する間違ったもの。
つまり、タイプFlyingMachine
のオブジェクトで動作するメソッドを記述し、Jet
やHelicopter
などのすべての種類のサブタイプを渡すことができ、これらのメソッドは常に正しいことを行います。すなわち、常に同じことを行うのではなく、適切なタイプのfly()
メソッドを呼び出す、つまり_"No implementation".
_を出力する
ポリモーフィズムは、この例では役に立ちません。
a)さまざまなタイプのオブジェクトがあり、それらがすべて同じAPIに準拠しているため、それらすべてのさまざまなタイプで動作できるクラスを作成できる場合に役立ちます。
b)また、既存のロジックを変更せずに新しいFlyingMachine
sをアプリケーションに追加できる場合にも役立ちます。
a)とb)は同じコインの両面です。
その方法をお見せしましょう。
_import Java.util.ArrayList;
import Java.util.List;
import static Java.lang.System.out;
public class PolymorphismDemo {
public static void main(String[] args) {
List<FlyingMachine> machines = new ArrayList<FlyingMachine>();
machines.add(new FlyingMachine());
machines.add(new Jet());
machines.add(new Helicopter());
machines.add(new Jet());
new MakeThingsFly().letTheMachinesFly(machines);
}
}
class MakeThingsFly {
public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
class FlyingMachine {
public void fly() {
out.println("No implementation");
}
}
class Jet extends FlyingMachine {
@Override
public void fly() {
out.println("Start, taxi, fly");
}
public void bombardment() {
out.println("Fire missile");
}
}
class Helicopter extends FlyingMachine {
@Override
public void fly() {
out.println("Start vertically, hover, fly");
}
}
_
a)MakeThingsFly
クラスは、FlyingMachine
型のすべてのクラスで動作します。
b)メソッドletTheMachinesFly
も、新しいクラスを追加するときに変更なしで機能します(!)。たとえば、PropellerPlane
:
_public void letTheMachinesFly(List<FlyingMachine> flyingMachines) {
for (FlyingMachine flyingMachine : flyingMachines) {
flyingMachine.fly();
}
}
}
_
それがポリモーフィズムの力です。 open-closed-principle を実装できます。
ポリモーフィズムを使用する理由は、多くの異なるオブジェクトを取得する汎用フレームワークを構築するときです同じインターフェイスで。新しいタイプのオブジェクトを作成する場合、オブジェクトの「ルール」に従う限り、新しいオブジェクトタイプに対応するためにフレームワークを変更する必要はありません。
あなたの場合、より便利な例は、さまざまなタイプのFlyingMachinesを受け入れるオブジェクトタイプ「Airport」を作成することです。空港は、次のような「AllowPlaneToLand」関数を定義します。
//pseudocode
void AllowPlaneToLand(FlyingMachine fm)
{
fm.LandPlane();
}
FlyingMachineの各タイプが適切なLandPlaneメソッドを定義している限り、適切に着陸できます。空港は、飛行機を着陸させるために、FlyingMachineでLandPlaneを呼び出す必要があることを除いて、FlyingMachineについて何も知る必要はありません。したがって、空港はもはや変更する必要がなく、ハンドグライダー、UFO、パラシュートなど、新しいタイプのフライングマシンを受け入れ続けることができます。
したがって、ポリモーフィズムは、これらのオブジェクトを中心に構築され、変更することなくこれらのメソッドに一般的にアクセスできるフレームワークに役立ちます。
Jetsだけを使用する場合はあまり追加されません。別のFlyingMachinesを使用している場合、たとえば飛行機
より多くのクラスを含めるように変更したので、ポリモーフィズムの利点は、受け取るインスタンスの特定のタイプ(およびビジネスコンセプト)からの抽象化であり、ただそれが飛ぶことができることに気をつけます。
多態性 (ランタイムとコンパイル時間の両方)は、かなりの理由でJavaで必要です。
メソッドのオーバーライドは実行時ポリモーフィズムであり、オーバーロードはコンパイル時ポリモーフィズムです。
それらのいくつかはあります(それらのいくつかは既に議論されています):
Collections:複数のタイプの飛行機械があり、それらをすべて単一のコレクションに入れたいとします。タイプFlyingMachines
のリストを定義して、それらをすべて追加できます。
List<FlyingMachine> fmList = new ArrayList<>();
fmList.add(new new JetPlaneExtendingFlyingMachine());
fmList.add(new PassengerPlanePlaneExtendingFlyingMachine());
上記はポリモーフィズムによってのみ実行できます。それ以外の場合は、2つの個別のリストを維持する必要があります。
あるタイプを別のタイプに貼り付ける:オブジェクトを次のように宣言します:
FlyingMachine fm1 = new JetPlaneExtendingFlyingMachine();
FlyingMachine fm2 = new PassengerPlanePlaneExtendingFlyingMachine();
fm1 = fm2; //can be done
オーバーロード:指定したコードとは関係ありませんが、オーバーロードはcompile time polymorphism。
タイプFlyingMachine
を受け入れる単一のメソッドで、すべてのタイプ、つまりFlyingMachineのサブクラスを処理できます。 Polymorphism
でのみ達成できます。
flm.fly()
とj.fly()
の両方は、インスタンスの型が実際に同じであるため、同じ答えを与えます。つまり、Jet
です。したがって、これらは同じ動作をします。
次の場合に違いを確認できます。
_FlyingMachines flm = new FlyingMachines();
flm.fly();
Jet j = new Jet();
j.bombarment();
j.fly();
_
ポリモーフィズムは、振る舞いが異なる同じメソッドシグネチャとして定義されます。ご覧のとおり、FlyingMachines
とJet
の両方にメソッドfly()
が定義されていますが、メソッドの実装方法が異なるため、動作が異なると見なされます。
を参照してください
これにもう1つのクラスを追加しましょう。ポリモーフィズムの使用を理解するのに役立ちます。
class FlyingMachines {
public void fly() {
System.out.println("No implementation");
}
}
class Jet extends FlyingMachines {
public void fly() {
System.out.println("Start, Jet, Fly");
}
}
class FighterPlan extends FlyingMachines {
public void fly() {
System.out.println("Start, Fighter, Fight");
}
}
public class PolymorphicTest {
public static void main(String[] args) {
FlyingMachines flm = new Jet();
flm.fly();
FlyingMachines flm2 = new FighterPlan();
flm2.fly();
}
}
出力:
Start, Jet, Fly
Start, Fighter, Fight
ポリモーフィズムは、プロダクションレベルのコードを生成する「if」条件をコードが削除するのにも役立ちます。条件を削除すると、コードの可読性が向上し、より良いユニットテストケースを作成できるためです。 !(n階乗)の可能性。
方法を見てみましょう
flyingMachineクラスがあり、以下のようにFlyMachineのタイプを定義するコンストラクターで文字列を受け取る場合
class FlyingMachine{
private type;
public FlyingMachine(String type){
this.type = type;
}
public int getFlyingSpeedInMph {
if(type.equals("Jet"))
return 600;
if(type.equals("AirPlane"))
return 300;
}
}
FlyingMachineの2つのインスタンスを次のように作成できます。
FlyingMachine jet = new FlyingMachine("Jet");
FlyingMachine airPlane = new FlyingMachine("AirPlane");
を使用して速度を取得します
jet.fylingSpeedInMph();
airPlane.flyingSpeedInMph();
しかし、ポリモーフィズムを使用する場合、ジェネリックFlyMachineクラスを拡張し、以下のようにgetFlyingSpeedInMphをオーバーライドすることによりif条件を削除します
class interface FlyingMachine {
public int abstract getFlyingSpeedInMph;
}
class Jet extends FlyingMachine {
@Override
public int getFlyingSpeedInMph(){
return 600;
}
}
class Airplane extends FlyingMachine {
@Override
public int getFlyingSpeedInMph(){
return 600;
}
}
これで、以下のように飛行速度を取得できます
FlyingMachine jet = new Jet();
jet.flyingSpeed();
FlyingMachine airPlane = new AirPlane();
airPlane.flyingSpeed();
ポリモーフィズムは、ポリモーフィズムが必要な場合にのみメリットをもたらします。概念プロジェクトのエンティティが別のエンティティの特殊化とみなされる場合に使用されます。主なアイデアは「専門化」です。偉大な例は、たとえば生物に適用されるいわゆる分類法にあります。犬と人間はどちらも哺乳類です。つまり、クラスの哺乳類は、いくつかのプロパティと動作が共通しているすべてのエンティティをグループ化します。
また、ElectricCarとDieselCarは自動車の専門です。そのため、どちらもisThereFuel()を持っています。なぜなら、車を運転するときに、運転するのに十分な燃料があるかどうかを知ることができるからです。もう1つの素晴らしいコンセプトは「期待」です。
ソフトウェアを開始する前に、ソフトウェアのドメインのER(エンティティリレーションシップ)ダイアグラムを描画することは常に素晴らしいアイデアです。これは、作成されるエンティティの種類を想像する必要があり、十分な場合は、エンティティ間の共通の動作を見つける多くのコードを保存できるためです。しかし、良いプロジェクトの利点はコードの保存だけではありません。
いわゆる「ソフトウェアエンジニアリング」を見つけることに興味があるかもしれません。それは「クリーンコード」を書くことを可能にする技術と概念の集まりです(プログラムによって広く提案されている「クリーンコード」という素晴らしい本もあります) 。
ここで、この特定のコードでは、ポリモーフィズムの必要はありません。
ポリモーフィズムが必要な理由と時期を理解しましょう。
さまざまな種類のマシン(車、スクーター、洗濯機、電動機など)があり、すべてのマシンが起動および停止することがわかっているとします。ただし、マシンを起動および停止するロジックは、マシンごとに異なります。ここで、すべてのマシンには、起動と停止の異なる実装があります。したがって、異なる実装を提供するには、ポリモーフィズムが必要です。
ここでは、メソッドとしてstart()
およびstop()
を持つ基本クラスマシンを使用でき、各マシンタイプはこの機能と@Override
これらのメソッド。
多くの場合にマップされたポリモーフィズムは、それ自体で明確に述べられています。
Javaはおっと言語なので、抽象、オーバーロード、オーバーライドによる実装があります
Javaには実行時ポリモーフィズムの仕様がありません。
それにもいくつかの最高の例があります。
public abstract class Human {
public abstract String getGender();
}
class Male extends Human
{
@Override
public String getGender() {
return "male";
}
}
class Female extends Human
{
@Override
public String getGender() {
return "female";
}
}
オーバーライド
基本クラスの動作を再定義します。たとえば、ベースカーの移動の既存の機能に速度カウントを追加したいです。
オーバーロード
同じ名前で異なる署名の動作をすることができます。たとえば、特定の大統領ははっきりと大声で話しますが、別の大統領は大声でしか話しません。
ポリモーフィズムがJavaで必要になる理由は、概念が継承の実装に広く使用されているためです。異なる内部構造を持つオブジェクトが同じ外部インターフェースを共有できるようにする上で重要な役割を果たします。