Java:JavaでOverriding and Hiding Methods
8001 ワード
以前はオーバーライドとオーバーロードの違いを知っていただけで、普段は捕まえて使えばいいのですが、Javaを習うときは書き換え、置き換え、置き換え、隠し、オーバーロードなど、めちゃくちゃで、まとめて整理しておきます.
全体的にjavaは書き換え、非表示、再ロードの3種類しかありませんが、具体的には以下のようにまとめられます.
基本概念
メソッド署名:メソッド名+パラメータリスト(パラメータタイプ、個数、順序).
書き換える
書き換えは上書き、置換、置換とも呼ばれます.本文は一括して書き換えと呼ぶ.インスタンスメソッドのみ書き換えることができます!書き換えたメソッドはインスタンスメソッドのままでなければなりません.(インスタンスメソッド-書き換え-->インスタンスメソッド)メンバー変数と静的メソッドは書き換えることができず、非表示にするしかありません.
インスタンスメソッドの書き換え
スーパークラスParentにはインスタンスメソッドAがあり、サブクラスchildはAと「同じ署名とサブセット戻りタイプ」のインスタンスメソッドBを定義し、サブクラスオブジェクトChildObjは自分のインスタンスメソッドBのみを呼び出すことができる.サブクラスオブジェクトChildObjをスーパークラスオブジェクトParentObjに変換しても、ParentObjは書き換え後のインスタンスメソッドBのみを呼び出すことができます.(スーパークラスオブジェクトParentObjのインスタンスメソッドAはインスタンスメソッドBによって上書きされている)
書き換えた文法規則は次のとおりです.
(1)メソッド署名は同じ(パラメータタイプ、個数、順序)でなければならない.(2)返却タイプに要求があり、2つのケースに分けられる. a.書き換え方法の戻りタイプは基本タイプである:書き換え方法の戻りタイプは「同じ」でなければならない.基本タイプには(byte,short,int,long,float,double,char,boolean,実はvoidタイプも含まれている)が含まれていますが、戻りタイプがパッケージクラスである場合は以下の場合bに属することに注意してください. b.書き換え方法の戻りタイプは参照タイプである:書き換え方法の戻りタイプは「同じ」またはその「サブタイプ」であるべきである.参照タイプには、配列、stringなどのすべての非基本タイプのタイプ(すなわちクラスタイプ)が含まれます.
(3)書き換え方法のアクセス権限は書き換え方法のアクセス権限よりも小さくてはならず,より広範であってもよい.書き換え方法がパケットアクセス権である場合、書き換え方法はpublicアクセス権である.書き換え方法は、final、synchronized、native、strictfpなどの他の方法修飾子を変更することができる.書き換え方法にfinal修飾のパラメータがあるかどうかにかかわらず、書き換え方法は、このパラメータのfinal修飾子を増加、保持、削除することができる(パラメータ修飾子は方法署名に属さない).(4)書き換え方法で投げ出される異常範囲は、書き換え方法で投げ出される異常の範囲より大きくしてはならない(異常を投げ出さなくてもよい).(5)finalメソッドを書き換えることができない.(final修飾子の存在の意味は、任意のサブクラスがこの方法を書き換えることを防止することである)(6)static静的方法を書き換えることができない.(形式的には書くことができるが、本質的には書き換えるのではなく、以下に述べる隠しに属する)(7)一つの方法が継承されない場合は書き換えることができない.あるいは、メソッドがアクセスできる場合にのみ書き換えることができます.典型的にはスーパークラスのprivateメソッドです.
(3)について注意する必要がある:1.overrideの書き換えは戻りタイプに要求され、overloadの再ロードは戻りタイプに要求されない.リロードは戻りタイプを変更できます.コンパイラはメソッド署名の識別によって異なるメソッドを静的にコンパイルできるからである.これもjavaでのリロードと書き換えの違いの一つです.2.厳密には、書き換えはダイナミックバインド(またはダイナミックアセンブリと呼ばれる)であり、リロードは静的バインドであるため、コンパイル時に決定されるマルチステートに属する.
非表示
隠しと上書きは形式的に極めて似ている(文法規則)が、本質的な違いがある.
静的かどうかにかかわらず、メンバー変数と静的メソッドのみを非表示にできます.
メンバー変数
非表示メンバー変数:スーパークラスParentにはメンバー変数Aがあり、サブクラスChildはAと同じ名前のメンバー変数Bを定義し、サブクラスオブジェクトChildObjは自分のメンバー変数Bを呼び出します.サブクラスオブジェクトChildObjをスーパークラスオブジェクトParentObjに変換すると、ParentObjはスーパークラスのメンバー変数Aを呼び出す!注意1.メンバー変数を非表示にする場合は、同じ名前であれば変数タイプ(基本タイプでも非表示タイプでも)を変更できます.2.スーパークラスのprivateメンバー変数を非表示にすることはできません.つまり、アクセス可能なメンバー変数のみを非表示にすることができます.3.スーパークラスメンバー変数Aを非表示にする場合、Aがprivateでない限り、サブクラスメンバー変数Bのアクセス権を低下または向上させることができます.4.メンバー変数を非表示にするのは静的かどうかとは関係ありません.静的変数はインスタンス変数を非表示にしたり、インスタンス変数は静的変数を非表示にしたりできます.5.スーパークラスのfinalメンバー変数を非表示にできます.
スタティツクメソッド
非表示のメソッドは静的メソッドである必要があります.(静的メソッド-非表示-->静的メソッド)非表示静的メソッド:スーパークラスParentには静的メソッドAがあり、サブクラスChildはAと「同じ署名とサブセット戻りタイプ」の静的メソッドBを定義し、サブクラスオブジェクトChildObjは独自の静的メソッドBを呼び出す.サブクラスオブジェクトChildObjをスーパークラスオブジェクトParentObjに変換すると、ParentObjはスーパークラスの静的メソッドAを呼び出す!
スーパークラス静的メソッドを非表示にする構文ルールは、インスタンスメソッドを書き換えるルールとほぼ同じであり、(6)の項目を変更するだけで、(6)インスタンスメソッドを非表示にすることはできません.
継承に際して注意すべきいくつかの原則
1)サブクラスの静的メソッドで親クラスで同じように識別されたインスタンスメソッドを非表示にしようとするのは合法ではなく、コンパイラがエラーを報告する.2)子クラスのインスタンスメソッドで親クラスで同じ識別を上書きしようとする静的メソッドも合法ではなく、コンパイラがエラーを報告する.3)静的方法と最終方法はカバーできない;4)例示的な方法をカバーすることができる.5)抽象メソッドは特定のクラスで上書きされなければならない.
サンプルコード
出力結果:
全体的にjavaは書き換え、非表示、再ロードの3種類しかありませんが、具体的には以下のようにまとめられます.
基本概念
メソッド署名:メソッド名+パラメータリスト(パラメータタイプ、個数、順序).
書き換える
書き換えは上書き、置換、置換とも呼ばれます.本文は一括して書き換えと呼ぶ.インスタンスメソッドのみ書き換えることができます!書き換えたメソッドはインスタンスメソッドのままでなければなりません.(インスタンスメソッド-書き換え-->インスタンスメソッド)メンバー変数と静的メソッドは書き換えることができず、非表示にするしかありません.
インスタンスメソッドの書き換え
スーパークラスParentにはインスタンスメソッドAがあり、サブクラスchildはAと「同じ署名とサブセット戻りタイプ」のインスタンスメソッドBを定義し、サブクラスオブジェクトChildObjは自分のインスタンスメソッドBのみを呼び出すことができる.サブクラスオブジェクトChildObjをスーパークラスオブジェクトParentObjに変換しても、ParentObjは書き換え後のインスタンスメソッドBのみを呼び出すことができます.(スーパークラスオブジェクトParentObjのインスタンスメソッドAはインスタンスメソッドBによって上書きされている)
書き換えた文法規則は次のとおりです.
(1)メソッド署名は同じ(パラメータタイプ、個数、順序)でなければならない.(2)返却タイプに要求があり、2つのケースに分けられる.
(3)書き換え方法のアクセス権限は書き換え方法のアクセス権限よりも小さくてはならず,より広範であってもよい.書き換え方法がパケットアクセス権である場合、書き換え方法はpublicアクセス権である.書き換え方法は、final、synchronized、native、strictfpなどの他の方法修飾子を変更することができる.書き換え方法にfinal修飾のパラメータがあるかどうかにかかわらず、書き換え方法は、このパラメータのfinal修飾子を増加、保持、削除することができる(パラメータ修飾子は方法署名に属さない).(4)書き換え方法で投げ出される異常範囲は、書き換え方法で投げ出される異常の範囲より大きくしてはならない(異常を投げ出さなくてもよい).(5)finalメソッドを書き換えることができない.(final修飾子の存在の意味は、任意のサブクラスがこの方法を書き換えることを防止することである)(6)static静的方法を書き換えることができない.(形式的には書くことができるが、本質的には書き換えるのではなく、以下に述べる隠しに属する)(7)一つの方法が継承されない場合は書き換えることができない.あるいは、メソッドがアクセスできる場合にのみ書き換えることができます.典型的にはスーパークラスのprivateメソッドです.
(3)について注意する必要がある:1.overrideの書き換えは戻りタイプに要求され、overloadの再ロードは戻りタイプに要求されない.リロードは戻りタイプを変更できます.コンパイラはメソッド署名の識別によって異なるメソッドを静的にコンパイルできるからである.これもjavaでのリロードと書き換えの違いの一つです.2.厳密には、書き換えはダイナミックバインド(またはダイナミックアセンブリと呼ばれる)であり、リロードは静的バインドであるため、コンパイル時に決定されるマルチステートに属する.
非表示
隠しと上書きは形式的に極めて似ている(文法規則)が、本質的な違いがある.
静的かどうかにかかわらず、メンバー変数と静的メソッドのみを非表示にできます.
メンバー変数
非表示メンバー変数:スーパークラスParentにはメンバー変数Aがあり、サブクラスChildはAと同じ名前のメンバー変数Bを定義し、サブクラスオブジェクトChildObjは自分のメンバー変数Bを呼び出します.サブクラスオブジェクトChildObjをスーパークラスオブジェクトParentObjに変換すると、ParentObjはスーパークラスのメンバー変数Aを呼び出す!注意1.メンバー変数を非表示にする場合は、同じ名前であれば変数タイプ(基本タイプでも非表示タイプでも)を変更できます.2.スーパークラスのprivateメンバー変数を非表示にすることはできません.つまり、アクセス可能なメンバー変数のみを非表示にすることができます.3.スーパークラスメンバー変数Aを非表示にする場合、Aがprivateでない限り、サブクラスメンバー変数Bのアクセス権を低下または向上させることができます.4.メンバー変数を非表示にするのは静的かどうかとは関係ありません.静的変数はインスタンス変数を非表示にしたり、インスタンス変数は静的変数を非表示にしたりできます.5.スーパークラスのfinalメンバー変数を非表示にできます.
スタティツクメソッド
非表示のメソッドは静的メソッドである必要があります.(静的メソッド-非表示-->静的メソッド)非表示静的メソッド:スーパークラスParentには静的メソッドAがあり、サブクラスChildはAと「同じ署名とサブセット戻りタイプ」の静的メソッドBを定義し、サブクラスオブジェクトChildObjは独自の静的メソッドBを呼び出す.サブクラスオブジェクトChildObjをスーパークラスオブジェクトParentObjに変換すると、ParentObjはスーパークラスの静的メソッドAを呼び出す!
スーパークラス静的メソッドを非表示にする構文ルールは、インスタンスメソッドを書き換えるルールとほぼ同じであり、(6)の項目を変更するだけで、(6)インスタンスメソッドを非表示にすることはできません.
継承に際して注意すべきいくつかの原則
1)サブクラスの静的メソッドで親クラスで同じように識別されたインスタンスメソッドを非表示にしようとするのは合法ではなく、コンパイラがエラーを報告する.2)子クラスのインスタンスメソッドで親クラスで同じ識別を上書きしようとする静的メソッドも合法ではなく、コンパイラがエラーを報告する.3)静的方法と最終方法はカバーできない;4)例示的な方法をカバーすることができる.5)抽象メソッドは特定のクラスで上書きされなければならない.
サンプルコード
class Animal {
char hairColor='B';
int legNumber=2;
static boolean isHuman=true;
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
public void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
public class Cat extends Animal {
static int hairColor=1;
char legNumber='A';
double isHuman=3.1415926E5;
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}
public static void main(String[] args) {
System.out.println("========child class=========");
Cat myCat = new Cat();
System.out.println("myCat.hairColor="+myCat.hairColor);
System.out.println("myCat.legNumber="+myCat.legNumber);
System.out.println("myCat.isHuman="+myCat.isHuman);
myCat.testClassMethod();
myCat.testInstanceMethod();
System.out.println("========child class ---> parent class=========");
Animal myAnimal = myCat;
System.out.println("========parent class=========");
System.out.println("myAnimal.hairColor="+myAnimal.hairColor);
System.out.println("myAnimal.legNumber="+myAnimal.legNumber);
System.out.println("myAnimal.isHuman="+myAnimal.isHuman);
myAnimal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
出力結果:
========child class=========
myCat.hairColor=1
myCat.legNumber=A
myCat.isHuman=314159.26
The class method in Cat.
The instance method in Cat.
========child class ---> parent class=========
========parent class=========
myAnimal.hairColor=B
myAnimal.legNumber=2
myAnimal.isHuman=true
The class method in Animal.
The instance method in Cat.