Javaに関して、誰かが尋ねると:
ポリモーフィズムとは何ですか?
思いのオーバーロードまたはオーバーライド許容答えは?
それだけではない。
実装のないメソッドを定義した抽象基本クラスがあり、そのメソッドをサブクラスで定義した場合でも、それはオーバーライドされますか?
過負荷は確かに正しい答えではないと思います。
Javaに関して、誰かが尋ねると:
ポリモーフィズムとは何ですか?
思いのオーバーロードまたはオーバーライド許容答えは?
それだけではない。
実装のないメソッドを定義した抽象基本クラスがあり、そのメソッドをサブクラスで定義した場合でも、それはオーバーライドされますか?
過負荷は確かに正しい答えではないと思います。
回答:
ポリモーフィズムを表現する最も明確な方法は、抽象基本クラス(またはインターフェース)を使用することです
public abstract class Human{
...
public abstract void goPee();
}
goPee()
メソッドは人間には定義できないため、このクラスは抽象クラスです。これは、サブクラスMaleおよびFemaleに対してのみ定義可能です。また、人間は抽象的な概念です。男性でも女性でもない人間を作成することはできません。それはどちらかでなければなりません。
したがって、抽象クラスを使用して実装を延期します。
public class Male extends Human{
...
@Override
public void goPee(){
System.out.println("Stand Up");
}
}
そして
public class Female extends Human{
...
@Override
public void goPee(){
System.out.println("Sit Down");
}
}
今、私たちは人間でいっぱいの部屋全体に小便をするように言うことができます。
public static void main(String[] args){
ArrayList<Human> group = new ArrayList<Human>();
group.add(new Male());
group.add(new Female());
// ... add more...
// tell the class to take a pee break
for (Human person : group) person.goPee();
}
これを実行すると、次のようになります。
Stand Up
Sit Down
...
goPee
重力場を入力として取りません。このグローバルな状態への依存はユニットテストをCatheterizedIntersexAstronaut
困難にし、サブクラス化が常に特性の構成に最適な方法であるとは限らないことを示しています。
ポリモーフィズムとは、クラスインスタンスが、継承ツリー内の別のクラス(多くの場合、祖先クラスの1つ)のインスタンスであるかのように動作する機能です。たとえば、Javaでは、すべてのクラスがObjectから継承されます。したがって、Object型の変数を作成して、任意のクラスのインスタンスを割り当てることができます。
オーバーライド別のクラスから継承するクラスで発生する関数のタイプです。オーバーライド関数は、基本クラスから継承された関数を「置き換え」ますが、そのクラスのインスタンスがポリモーフィズムによって異なるタイプのふりをしている場合でも呼び出されるように置き換えます。前の例を参照すると、独自のクラスを定義して、toString()関数をオーバーライドできます。この関数はObjectから継承されているため、このクラスのインスタンスをObject型の変数にコピーすると、引き続き使用できます。通常、クラスがオブジェクトのふりをしているときにクラスでtoString()を呼び出すと、実際に起動するtoStringのバージョンは、オブジェクト自体で定義されたバージョンになります。ただし、関数はオーバーライドであるため、クラスインスタンスの場合でも、クラスのtoString()の定義が使用されます。
オーバーロードは、同じ名前でパラメータが異なる複数のメソッドを定義するアクションです。オーバーライドや多態性とは無関係です。
Ad hoc polymorphism
あなたに説明するものであるオーバーロードセクションとある多型の場合。
ポリモーフィズムとは、複数のフォーム、同じオブジェクトが要件に従って異なる操作を実行することを意味します。
ポリモーフィズムは、2つの方法で実現できます。
メソッドのオーバーロードとは、同じクラスに同じメソッド名を使用して2つ以上のメソッドを書き込むことですが、渡すパラメーターが異なります。
メソッドのオーバーライドは、異なるクラスでメソッド名を使用することを意味します。つまり、親クラスのメソッドが子クラスで使用されます。
Javaでは、ポリモーフィズムを実現するために、スーパークラス参照変数がサブクラスオブジェクトを保持できます。
ポリモーフィズムを実現するには、すべての開発者がプロジェクトで同じメソッド名を使用する必要があります。
擬似C#/ Javaでのポリモーフィズムの例を次に示します。
class Animal
{
abstract string MakeNoise ();
}
class Cat : Animal {
string MakeNoise () {
return "Meow";
}
}
class Dog : Animal {
string MakeNoise () {
return "Bark";
}
}
Main () {
Animal animal = Zoo.GetAnimal ();
Console.WriteLine (animal.MakeNoise ());
}
Main関数は動物の種類を認識せず、MakeNoise()メソッドの特定の実装の動作に依存します。
編集:ブライアンは私にパンチを打ったように見えます。おかしい、同じ例を使用しました。しかし、上記のコードは概念を明確にするのに役立ちます。
オーバーライドとオーバーロードの両方を使用して、ポリモーフィズムを実現します。
1つ以上のサブクラスでオーバーライドされるクラスにメソッドを含めることができます。このメソッドは、オブジェクトのインスタンス化に使用されたクラスに応じて、さまざまな処理を行います。
abstract class Beverage {
boolean isAcceptableTemperature();
}
class Coffee extends Beverage {
boolean isAcceptableTemperature() {
return temperature > 70;
}
}
class Wine extends Beverage {
boolean isAcceptableTemperature() {
return temperature < 10;
}
}
2つ以上の引数のセットでオーバーロードされるメソッドを使用することもでき ます。このメソッドは、渡された引数のタイプに基づいてさまざまなことを行います。
class Server {
public void pour (Coffee liquid) {
new Cup().fillToTopWith(liquid);
}
public void pour (Wine liquid) {
new WineGlass().fillHalfwayWith(liquid);
}
public void pour (Lemonade liquid, boolean ice) {
Glass glass = new Glass();
if (ice) {
glass.fillToTopWith(new Ice());
}
glass.fillToTopWith(liquid);
}
}
あなたは過負荷が答えではないことは正しいです。
どちらもオーバーライドされていません。オーバーライドは、ポリモーフィズムを取得する手段です。ポリモーフィズムとは、オブジェクトがそのタイプに基づいて動作を変化させる機能です。これは、ポリモーフィズムを示すオブジェクトの呼び出し元がオブジェクトの特定のタイプを認識していない場合に最もよく示されます。
具体的には、オーバーロードまたはオーバーライドすることで全体像がわかりません。ポリモーフィズムとは、オブジェクトのタイプに基づいてその動作を特殊化する機能です。
同じ名前のメソッドが異なる動作をして異なるパラメーター型を与えることができる場合のオーバーロードは多態性(パラメトリック多態性)の一種であるという点で、私はここでの答えのいくつかに同意しません。良い例は、オペレーターのオーバーロードです。「+」を定義して、さまざまなタイプのパラメーター(文字列やintなど)を受け入れることができます。これらのタイプに基づいて、「+」の動作は異なります。
ポリモーフィズムには、継承およびオーバーライドメソッドも含まれますが、基本タイプでは抽象または仮想にすることができます。継承ベースのポリモーフィズムに関して、Javaは単一クラスの継承のみをサポートし、ポリモーフィックな動作を基本型の単一チェーンの振る舞いに制限します。Javaは、ポリモーフィック動作のさらに別の形式である複数のインターフェースの実装をサポートしています。
ポリモーフィズムとは単に「多くの形式」を意味します。
継承を実現する必要はありません...継承ではないインターフェイスの実装が多態的なニーズに対応するためです。おそらく、インターフェイスの実装は、継承よりも「より良い」多態的なニーズに対応します。
たとえば、飛ぶことができるすべてのものを記述するスーパークラスを作成しますか?私は考えるべきではありません。フライトを説明するインターフェースを作成し、そのままにしておくのが最善です。
したがって、インターフェースは振る舞いを記述し、メソッド名は(プログラマーにとって)振る舞いを記述しているため、メソッドのオーバーロードをポリモーフィズムのより低い形式と見なすことはそれほど難しいことではありません。
どちらでもない:
オーバーロードとは、異なるパラメーターをとる同じ関数名がある場合です。
オーバーライドとは、子クラスが親のメソッドを独自のメソッドで置き換えるときです(これ自体は、ポリモーフィズムを構成しません)。
ポリモーフィズムは遅延バインディングです。たとえば、基本クラス(親)メソッドが呼び出されますが、アプリケーションが実際のオブジェクトが何であるかをアプリケーションが認識するまでは、メソッドが異なる子クラスである可能性があります。これは、基本クラスが定義されている場所で任意の子クラスを使用できるためです。
Javaでは、コレクションライブラリでポリモーフィズムがよく見られます。
int countStuff(List stuff) {
return stuff.size();
}
Listは基本クラスです。リンクされたリスト、ベクトル、配列、またはカスタムリストの実装を数える場合、リストのように機能する限り、コンパイラーは手掛かりがありません。
List myStuff = new MyTotallyAwesomeList();
int result = countStuff(myStuff);
オーバーロードしている場合は、次のようになります。
int countStuff(LinkedList stuff) {...}
int countStuff(ArrayList stuff) {...}
int countStuff(MyTotallyAwesomeList stuff) {...}
etc...
そして、countStuff()の正しいバージョンは、パラメーターと一致するようにコンパイラーによって選択されます。
ポリモーフィズムについては、この投稿ですでに詳細に説明されていますが、なぜその一部なのかについてもっと強調したいと思います。
ポリモーフィズムがOOP言語で非常に重要である理由。
継承/ポリモーフィズムの有無にかかわらず、テレビ用のシンプルなアプリケーションを作成してみましょう。アプリケーションの各バージョンを投稿し、小さな回顧を行います。
あなたがテレビ会社のソフトウェアエンジニアであり、ボリューム、明るさ、カラーコントローラーのソフトウェアを記述して、ユーザーコマンドでそれらの値を増減させると仮定します。
追加することにより、これらの各機能のクラスを作成することから始めます。
アプリケーションバージョン1
import java.util.Scanner;
class VolumeControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class BrightnessControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ColourControllerV1 {
private int value;
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
/*
* There can be n number of controllers
* */
public class TvApplicationV1 {
public static void main(String[] args) {
VolumeControllerV1 volumeControllerV1 = new VolumeControllerV1();
BrightnessControllerV1 brightnessControllerV1 = new BrightnessControllerV1();
ColourControllerV1 colourControllerV1 = new ColourControllerV1();
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println("Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV1.adjust(5);
break;
}
case 2: {
volumeControllerV1.adjust(-5);
break;
}
case 3: {
brightnessControllerV1.adjust(5);
break;
}
case 4: {
brightnessControllerV1.adjust(-5);
break;
}
case 5: {
colourControllerV1.adjust(5);
break;
}
case 6: {
colourControllerV1.adjust(-5);
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
これで、デプロイする準備ができた作業用アプリケーションの最初のバージョンができました。これまでに行われた作業を分析する時間。
TVアプリケーションバージョン1の問題
アプリケーションが期待どおりに動作する限り、それを維持することにします。
時々、上司が戻ってきて、既存のアプリケーションにリセット機能を追加するように求めてきます。リセットすると、3つすべての3つのコントローラーがそれぞれのデフォルト値に設定されます。
新しい機能の新しいクラス(ResetFunctionV2)の作成を開始し、この新しい機能のユーザー入力マッピングコードをマップします。
アプリケーションバージョン2
import java.util.Scanner;
class VolumeControllerV2 {
private int defaultValue = 25;
private int value;
int getDefaultValue() {
return defaultValue;
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class BrightnessControllerV2 {
private int defaultValue = 50;
private int value;
int get() {
return value;
}
int getDefaultValue() {
return defaultValue;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ColourControllerV2 {
private int defaultValue = 40;
private int value;
int get() {
return value;
}
int getDefaultValue() {
return defaultValue;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class ResetFunctionV2 {
private VolumeControllerV2 volumeControllerV2 ;
private BrightnessControllerV2 brightnessControllerV2;
private ColourControllerV2 colourControllerV2;
ResetFunctionV2(VolumeControllerV2 volumeControllerV2, BrightnessControllerV2 brightnessControllerV2, ColourControllerV2 colourControllerV2) {
this.volumeControllerV2 = volumeControllerV2;
this.brightnessControllerV2 = brightnessControllerV2;
this.colourControllerV2 = colourControllerV2;
}
void onReset() {
volumeControllerV2.set(volumeControllerV2.getDefaultValue());
brightnessControllerV2.set(brightnessControllerV2.getDefaultValue());
colourControllerV2.set(colourControllerV2.getDefaultValue());
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV2 {
public static void main(String[] args) {
VolumeControllerV2 volumeControllerV2 = new VolumeControllerV2();
BrightnessControllerV2 brightnessControllerV2 = new BrightnessControllerV2();
ColourControllerV2 colourControllerV2 = new ColourControllerV2();
ResetFunctionV2 resetFunctionV2 = new ResetFunctionV2(volumeControllerV2, brightnessControllerV2, colourControllerV2);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV2.adjust(5);
break;
}
case 2: {
volumeControllerV2.adjust(-5);
break;
}
case 3: {
brightnessControllerV2.adjust(5);
break;
}
case 4: {
brightnessControllerV2.adjust(-5);
break;
}
case 5: {
colourControllerV2.adjust(5);
break;
}
case 6: {
colourControllerV2.adjust(-5);
break;
}
case 7: {
resetFunctionV2.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
したがって、リセット機能を使用してアプリケーションを準備できます。しかし、今あなたはそれを実現し始めます
TVアプリケーションバージョン2の問題
同時に、起動時に各コントローラーが会社のホストされているドライバーリポジトリからインターネット経由で最新バージョンのドライバーをチェックする必要がある機能を追加する必要がある可能性があることをボスから聞いています。
ここで、追加するこの新しい機能はリセット機能に似ていると考え始め、アプリケーションをリファクタリングしない場合、アプリケーションの問題(V2)が増加します。
JAVAのポリモーフィック機能を利用できるように継承の使用を考え始め、新しい抽象クラス(ControllerV3)を追加します。
これらの改善により、TVアプリケーションのバージョン3が用意されました。
アプリケーションバージョン3
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
abstract class ControllerV3 {
abstract void set(int value);
abstract int get();
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
abstract void setDefault();
}
class VolumeControllerV3 extends ControllerV3 {
private int defaultValue = 25;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
}
class BrightnessControllerV3 extends ControllerV3 {
private int defaultValue = 50;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
}
class ColourControllerV3 extends ControllerV3 {
private int defaultValue = 40;
private int value;
public void setDefault() {
set(defaultValue);
}
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
}
class ResetFunctionV3 {
private List<ControllerV3> controllers = null;
ResetFunctionV3(List<ControllerV3> controllers) {
this.controllers = controllers;
}
void onReset() {
for (ControllerV3 controllerV3 :this.controllers) {
controllerV3.setDefault();
}
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV3 {
public static void main(String[] args) {
VolumeControllerV3 volumeControllerV3 = new VolumeControllerV3();
BrightnessControllerV3 brightnessControllerV3 = new BrightnessControllerV3();
ColourControllerV3 colourControllerV3 = new ColourControllerV3();
List<ControllerV3> controllerV3s = new ArrayList<>();
controllerV3s.add(volumeControllerV3);
controllerV3s.add(brightnessControllerV3);
controllerV3s.add(colourControllerV3);
ResetFunctionV3 resetFunctionV3 = new ResetFunctionV3(controllerV3s);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV3.adjust(5);
break;
}
case 2: {
volumeControllerV3.adjust(-5);
break;
}
case 3: {
brightnessControllerV3.adjust(5);
break;
}
case 4: {
brightnessControllerV3.adjust(-5);
break;
}
case 5: {
colourControllerV3.adjust(5);
break;
}
case 6: {
colourControllerV3.adjust(-5);
break;
}
case 7: {
resetFunctionV3.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
V2の問題リストにリストされている問題のほとんどは、
TVアプリケーションバージョン3の問題
繰り返しますが、この問題を解決することを考えます。これで、実装する別の機能(起動時のドライバーの更新)も用意できました。修正しないと、新しい機能にも複製されます。
したがって、抽象クラスで定義されたコントラクトを分割し、2つのインターフェイスを記述します。
そしてあなたの最初の具象クラスに以下のようにそれらを実装させます
アプリケーションバージョン4
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
interface OnReset {
void setDefault();
}
interface OnStart {
void checkForDriverUpdate();
}
abstract class ControllerV4 implements OnReset,OnStart {
abstract void set(int value);
abstract int get();
void adjust(int value) {
int temp = this.get();
if(((value > 0) && (temp >= 100)) || ((value < 0) && (temp <= 0))) {
System.out.println("Can not adjust any further");
return;
}
this.set(temp + value);
}
}
class VolumeControllerV4 extends ControllerV4 {
private int defaultValue = 25;
private int value;
@Override
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of VolumeController \t"+this.value);
this.value = value;
System.out.println("New value of VolumeController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for VolumeController .... Done");
}
}
class BrightnessControllerV4 extends ControllerV4 {
private int defaultValue = 50;
private int value;
@Override
int get() {
return value;
}
@Override
void set(int value) {
System.out.println("Old value of BrightnessController \t"+this.value);
this.value = value;
System.out.println("New value of BrightnessController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for BrightnessController .... Done");
}
}
class ColourControllerV4 extends ControllerV4 {
private int defaultValue = 40;
private int value;
@Override
int get() {
return value;
}
void set(int value) {
System.out.println("Old value of ColourController \t"+this.value);
this.value = value;
System.out.println("New value of ColourController \t"+this.value);
}
@Override
public void setDefault() {
set(defaultValue);
}
@Override
public void checkForDriverUpdate() {
System.out.println("Checking driver update for ColourController .... Done");
}
}
class ResetFunctionV4 {
private List<OnReset> controllers = null;
ResetFunctionV4(List<OnReset> controllers) {
this.controllers = controllers;
}
void onReset() {
for (OnReset onreset :this.controllers) {
onreset.setDefault();
}
}
}
class InitializeDeviceV4 {
private List<OnStart> controllers = null;
InitializeDeviceV4(List<OnStart> controllers) {
this.controllers = controllers;
}
void initialize() {
for (OnStart onStart :this.controllers) {
onStart.checkForDriverUpdate();
}
}
}
/*
* so on
* There can be n number of controllers
*
* */
public class TvApplicationV4 {
public static void main(String[] args) {
VolumeControllerV4 volumeControllerV4 = new VolumeControllerV4();
BrightnessControllerV4 brightnessControllerV4 = new BrightnessControllerV4();
ColourControllerV4 colourControllerV4 = new ColourControllerV4();
List<ControllerV4> controllerV4s = new ArrayList<>();
controllerV4s.add(brightnessControllerV4);
controllerV4s.add(volumeControllerV4);
controllerV4s.add(colourControllerV4);
List<OnStart> controllersToInitialize = new ArrayList<>();
controllersToInitialize.addAll(controllerV4s);
InitializeDeviceV4 initializeDeviceV4 = new InitializeDeviceV4(controllersToInitialize);
initializeDeviceV4.initialize();
List<OnReset> controllersToReset = new ArrayList<>();
controllersToReset.addAll(controllerV4s);
ResetFunctionV4 resetFunctionV4 = new ResetFunctionV4(controllersToReset);
OUTER: while(true) {
Scanner sc=new Scanner(System.in);
System.out.println(" Enter your option \n Press 1 to increase volume \n Press 2 to decrease volume");
System.out.println(" Press 3 to increase brightness \n Press 4 to decrease brightness");
System.out.println(" Press 5 to increase color \n Press 6 to decrease color");
System.out.println(" Press 7 to reset TV \n Press any other Button to shutdown");
int button = sc.nextInt();
switch (button) {
case 1: {
volumeControllerV4.adjust(5);
break;
}
case 2: {
volumeControllerV4.adjust(-5);
break;
}
case 3: {
brightnessControllerV4.adjust(5);
break;
}
case 4: {
brightnessControllerV4.adjust(-5);
break;
}
case 5: {
colourControllerV4.adjust(5);
break;
}
case 6: {
colourControllerV4.adjust(-5);
break;
}
case 7: {
resetFunctionV4.onReset();
break;
}
default:
System.out.println("Shutting down...........");
break OUTER;
}
}
}
}
これで、あなたが直面しているすべての問題が解決され、継承とポリモーフィズムを使用することで、
お役に立てれば :-)
ポリモーフィズムとは何ですか?
Java チュートリアルから
多型の辞書定義は、生物または種が多くの異なる形態または段階を持つことができる生物学の原理を指します。この原則は、オブジェクト指向プログラミングやJava言語などの言語にも適用できます。クラスのサブクラスは、独自の動作を定義しながら、親クラスと同じ機能の一部を共有できます。
例と定義を検討することにより、オーバーライドは受け入れられた答えになります。
2番目のクエリについて:
実装のないメソッドを定義した抽象基本クラスがあり、そのメソッドをサブクラスで定義した場合でも、それはオーバーライドされますか?
オーバーライドと呼ばれるべきです。
さまざまなタイプのオーバーライドを理解するには、この例をご覧ください。
super.methodName()
、最初のステートメントとしてコードスニペット:
import java.util.HashMap;
abstract class Game implements Runnable{
protected boolean runGame = true;
protected Player player1 = null;
protected Player player2 = null;
protected Player currentPlayer = null;
public Game(){
player1 = new Player("Player 1");
player2 = new Player("Player 2");
currentPlayer = player1;
initializeGame();
}
/* Type 1: Let subclass define own implementation. Base class defines abstract method to force
sub-classes to define implementation
*/
protected abstract void initializeGame();
/* Type 2: Sub-class can change the behaviour. If not, base class behaviour is applicable */
protected void logTimeBetweenMoves(Player player){
System.out.println("Base class: Move Duration: player.PlayerActTime - player.MoveShownTime");
}
/* Type 3: Base class provides implementation. Sub-class can enhance base class implementation by calling
super.methodName() in first line of the child class method and specific implementation later */
protected void logGameStatistics(){
System.out.println("Base class: logGameStatistics:");
}
/* Type 4: Template method: Structure of base class can't be changed but sub-class can some part of behaviour */
protected void runGame() throws Exception{
System.out.println("Base class: Defining the flow for Game:");
while ( runGame) {
/*
1. Set current player
2. Get Player Move
*/
validatePlayerMove(currentPlayer);
logTimeBetweenMoves(currentPlayer);
Thread.sleep(500);
setNextPlayer();
}
logGameStatistics();
}
/* sub-part of the template method, which define child class behaviour */
protected abstract void validatePlayerMove(Player p);
protected void setRunGame(boolean status){
this.runGame = status;
}
public void setCurrentPlayer(Player p){
this.currentPlayer = p;
}
public void setNextPlayer(){
if ( currentPlayer == player1) {
currentPlayer = player2;
}else{
currentPlayer = player1;
}
}
public void run(){
try{
runGame();
}catch(Exception err){
err.printStackTrace();
}
}
}
class Player{
String name;
Player(String name){
this.name = name;
}
public String getName(){
return name;
}
}
/* Concrete Game implementation */
class Chess extends Game{
public Chess(){
super();
}
public void initializeGame(){
System.out.println("Child class: Initialized Chess game");
}
protected void validatePlayerMove(Player p){
System.out.println("Child class: Validate Chess move:"+p.getName());
}
protected void logGameStatistics(){
super.logGameStatistics();
System.out.println("Child class: Add Chess specific logGameStatistics:");
}
}
class TicTacToe extends Game{
public TicTacToe(){
super();
}
public void initializeGame(){
System.out.println("Child class: Initialized TicTacToe game");
}
protected void validatePlayerMove(Player p){
System.out.println("Child class: Validate TicTacToe move:"+p.getName());
}
}
public class Polymorphism{
public static void main(String args[]){
try{
Game game = new Chess();
Thread t1 = new Thread(game);
t1.start();
Thread.sleep(1000);
game.setRunGame(false);
Thread.sleep(1000);
game = new TicTacToe();
Thread t2 = new Thread(game);
t2.start();
Thread.sleep(1000);
game.setRunGame(false);
}catch(Exception err){
err.printStackTrace();
}
}
}
出力:
Child class: Initialized Chess game
Base class: Defining the flow for Game:
Child class: Validate Chess move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate Chess move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
Child class: Add Chess specific logGameStatistics:
Child class: Initialized TicTacToe game
Base class: Defining the flow for Game:
Child class: Validate TicTacToe move:Player 1
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Child class: Validate TicTacToe move:Player 2
Base class: Move Duration: player.PlayerActTime - player.MoveShownTime
Base class: logGameStatistics:
皆さんはあなたがコンセプトを混合していると思います。ポリモーフィズムとは、オブジェクトが実行時に異なる動作をする能力です。これを実現するには、次の2つの要件が必要です。
とは言っても、オーバーロードは、使用している言語によってはオーバーライドとは異なることを意味します。たとえば、Javaにはオーバーライドではなく、オーバーロードが存在します。基本クラスとは異なるシグニチャーを持つオーバーロードされたメソッドは、サブクラスで使用できます。そうでない場合、それらはオーバーライドされます(オブジェクトの外部から基本クラスのメソッドを呼び出す方法がないということを意味します)。
ただし、C ++ではそうではありません。任意のオーバーロードされたメソッドは、独立して、署名が(diffrrent量、異なるタイプ)が同じであるか否かだけでなくとしてある上書き。つまり、現在、基本クラスのメソッドは、サブクラスオブジェクトの外部から呼び出されたときに、サブクラスで使用できなくなります。
したがって、答えは、Javaの使用のオーバーロードについて話すときです。他の言語ではc ++で発生するため、異なる場合があります
ポリモーフィズムは、その意味に関する限り、JavaでOVERRIDING する可能性が高くなります
それはすべて、さまざまな状況でのSAMEオブジェクトのさまざまな動作に関するものです(プログラミングの方法では、さまざまな引数を呼び出すことができます)。
以下の例は理解するのに役立つと思います...それは純粋なJavaコードではありませんが...
public void See(Friend)
{
System.out.println("Talk");
}
しかし、引数を変更すると...動作が変更されます...
public void See(Enemy)
{
System.out.println("Run");
}
Person(ここでは「オブジェクト」)は同じです...
ポリモーフィズムは、オブジェクトの複数の実装であるか、オブジェクトの複数の形式と言えます。Animals
抽象基本クラスとしてクラスがありmovement()
、動物が動く方法を定義すると呼ばれるメソッドがあるとします。現在、実際にはさまざまな種類の動物がいます。動物の動きも異なります。2本足の動物もあれば、4本足の動物もあれば、足のないmovement()
動物もいます。ただし、クラスDogs
Cats
Fish
など、より多くのクラスを定義する必要があります。次に、これらのクラスを基本クラスから拡張し、Animals
そのメソッドをオーバーライドする必要がありますmovement()
し、を、各動物に基づく新しい移動機能で必要があります。あなたも使うことができますInterfaces
それを達成するために。ここのキーワードはオーバーライドされ、オーバーロードは異なり、ポリモーフィズムとは見なされません。オーバーロードを使用すると、「同じ名前」で複数のメソッドを定義できますが、同じオブジェクトまたはクラスに異なるパラメーターを使用できます。
ポリモーフィズムは、単一のインターフェースを使用することにより、異なるオブジェクトを均一に処理させる言語の能力に関連しています。そのため、オーバーライドに関連しているため、インターフェース(または基本クラス)はポリモーフィックであり、実装者はオーバーライドするオブジェクト(同じメダルの2つの面)です。
とにかく、2つの用語の違いは、c ++などの他の言語を使用してより適切に説明されます。c++のポリモーフィックオブジェクトは、ベース関数が仮想の場合、Javaの対応オブジェクトとして動作しますが、メソッドが仮想でない場合、コードジャンプは静的に解決されます。真の型は実行時にチェックされないため、ポリモーフィズムには、オブジェクトへのアクセスに使用されるインターフェイスに応じて異なる動作をする機能が含まれます。擬似コードの例を作ってみましょう:
class animal {
public void makeRumor(){
print("thump");
}
}
class dog extends animal {
public void makeRumor(){
print("woff");
}
}
animal a = new dog();
dog b = new dog();
a.makeRumor() -> prints thump
b.makeRumor() -> prints woff
(makeRumorが仮想ではないと仮定)
javaは、このレベルのポリモーフィズム(オブジェクトスライスとも呼ばれます)を提供していません。
動物a = new dog(); 犬b =新しい犬();
a.makeRumor() -> prints thump
b.makeRumor() -> prints woff
どちらの場合も、woffのみが出力されます。aとbはクラスdogを参照しているため
import java.io.IOException;
class Super {
protected Super getClassName(Super s) throws IOException {
System.out.println(this.getClass().getSimpleName() + " - I'm parent");
return null;
}
}
class SubOne extends Super {
@Override
protected Super getClassName(Super s) {
System.out.println(this.getClass().getSimpleName() + " - I'm Perfect Overriding");
return null;
}
}
class SubTwo extends Super {
@Override
protected Super getClassName(Super s) throws NullPointerException {
System.out.println(this.getClass().getSimpleName() + " - I'm Overriding and Throwing Runtime Exception");
return null;
}
}
class SubThree extends Super {
@Override
protected SubThree getClassName(Super s) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Returning SubClass Type");
return null;
}
}
class SubFour extends Super {
@Override
protected Super getClassName(Super s) throws IOException {
System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and Throwing Narrower Exception ");
return null;
}
}
class SubFive extends Super {
@Override
public Super getClassName(Super s) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Overriding and have broader Access ");
return null;
}
}
class SubSix extends Super {
public Super getClassName(Super s, String ol) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading ");
return null;
}
}
class SubSeven extends Super {
public Super getClassName(SubSeven s) {
System.out.println(this.getClass().getSimpleName()+ " - I'm Perfect Overloading because Method signature (Argument) changed.");
return null;
}
}
public class Test{
public static void main(String[] args) throws Exception {
System.out.println("Overriding\n");
Super s1 = new SubOne(); s1.getClassName(null);
Super s2 = new SubTwo(); s2.getClassName(null);
Super s3 = new SubThree(); s3.getClassName(null);
Super s4 = new SubFour(); s4.getClassName(null);
Super s5 = new SubFive(); s5.getClassName(null);
System.out.println("Overloading\n");
SubSix s6 = new SubSix(); s6.getClassName(null, null);
s6 = new SubSix(); s6.getClassName(null);
SubSeven s7 = new SubSeven(); s7.getClassName(s7);
s7 = new SubSeven(); s7.getClassName(new Super());
}
}