2013-05-01 7 views
42

Javadocを混乱さは言う:Javaでメソッド隠蔽とは何ですか?でもJavaDocでの説明は

呼び出されます隠された方法のバージョンは、スーパークラスでは一つであり、そして呼び出されるオーバーライドされたメソッドのバージョンは、サブクラス内の1つのです。

私に鐘を鳴らしません。これの意味を明確に示す例は非常に高く評価されます。

答えて

97
public class Animal { 
    public static void foo() { 
     System.out.println("Animal"); 
    } 
} 

public class Cat extends Animal { 
    public static void foo() { // hides Animal.foo() 
     System.out.println("Cat"); 
    } 
} 

Cat.foo()Animal.foo()を非表示にすると言われています。静的メソッドは多態性ではないため、隠蔽はオーバーライドのようには機能しません。したがって、次のようになります。

Animal.foo(); // prints Animal 
Cat.foo(); // prints Cat 

Animal a = new Animal(); 
Animal b = new Cat(); 
Cat c = new Cat(); 
Animal d = null; 

a.foo(); // should not be done. Prints Animal 
b.foo(); // should not be done. Prints Animal because the declared type of b is Animal 
c.foo(); // should not be done. Prints Cat because the declared type of c is Cat 
d.foo(); // should not be done. Prints Animal because the declared type of b is Animal 

クラスではなくインスタンスで静的メソッドを呼び出すことは非常に悪いことです。決して実行しないでください。

多態性で上書きされるインスタンスメソッドとこれを比較してください。呼び出されたメソッドは、オブジェクトの具体的な、実行時の型によって異なります。

public class Animal { 
    public void foo() { 
     System.out.println("Animal"); 
    } 
} 

public class Cat extends Animal { 
    public void foo() { // overrides Animal.foo() 
     System.out.println("Cat"); 
    } 
} 

その後、次の処理が行われます。

Animal a = new Animal(); 
Animal b = new Cat(); 
Animal c = new Cat(); 
Animal d = null; 

a.foo(); // prints Animal 
b.foo(); // prints Cat 
c.foo(); // prints Cat 
d.foo(): // throws NullPointerException 
+15

非常に良い答えですが、インスタンス上で静的メソッドを呼び出すことは悪いと述べた人はあなただけです。 +1 –

+1

私はまだsuper.fooのようなものを言って親クラスのメソッドにアクセスできますか?ここで何が隠れているのですか?その関数は、呼び出される関数がインスタンスではなく参照変数に関連付けられているという事実を繰り返すだけです。まだこの用語の具体的な必要性を理解することはできません。 – JATMON

+7

'super'は、' this'のように、静的コンテキストでは使用できません。しかし、Cat.foo()から 'Animal.foo()'を呼び出すことはできますが、2つのメソッドは実際には名前とシグネチャ以外は共通していません。隠蔽は、上書きと区別するために使用されます。しかし、メソッドの隠蔽は実際には有用ではありませんが、メソッドのオーバーライドはオブジェクト指向設計の重要な部分です。 –

1

たとえば、静的ではなくスーパークラスのインスタンスメソッドをオーバーライドすることができます。

親クラスにはFooという名前の静的メソッドがあり、サブクラスにもFooという静的メソッドがあります。

もう1つのシナリオは、親にはCatという静的メソッドがあり、サブクラスにはCatというインスタンスメソッドがあります。 (静的で同じシグネチャのインスタンスは混在できません)。ここで

public class Animal { 

    public static String getCat() { return "Cat"; } 

    public boolean isAnimal() { return true; } 
} 

public class Dog extends Animal { 

    // Method hiding 
    public static String getCat() { } 

    // Not method hiding 
    @Override 
    public boolean isAnimal() { return false; } 
} 
2

へはを上書きする方法はいつでもメソッドがオブジェクトで呼び出されることを意味します派生クラスの新しい実装が呼び出されます。

メソッドは、このクラスのスコープ(つまり、そのメソッドの本体またはこのクラスの名前で修飾されたボディ)で、その名前への非修飾呼び出しが完全に呼び出されることを意味します。別の関数は、親クラスの同じ名前の静的メソッドにアクセスするための修飾を必要とします

詳細な説明Java Inheritance: Overwritten or hidden methods

1

サブクラスがスーパークラスのクラスメソッドと同じシグネチャを持つクラスのメソッドを定義する場合、サブクラスのメソッドはスーパークラスの一方を非表示にします。

隠しメソッドは静的コンテキストにあります。静的メソッドは、それ自体がオーバーライドされません。メソッド呼び出しの解決は、コンパイル時にコンパイラによって行われるためです。したがって、親クラスにあるものと同じシグニチャーを持つ基本クラスに静的メソッドを定義すると、そのサブクラスのメソッドはスーパークラスから継承したメソッドを隠します。

class Foo { 
    public static void method() { 
    System.out.println("in Foo"); 
    } 
} 

class Bar extends Foo { 
    public static void method() { 
    System.out.println("in Bar"); 
    } 
} 
26

方法隠すことによって意味される何まず第一に?

メソッドの隠蔽は、サブクラスがスーパークラスのクラスメソッドと同じシグネチャとクラスメソッドを定義した意味します。その場合、スーパークラスのメソッドはサブクラスによって隠されます。 実行されるメソッドのバージョンはNOTであり、呼び出すために使用されるオブジェクトによって決定されます。実際にはメソッドを呼び出すのに使用されるタイプの参照変数によって決定されます。

メソッドオーバーライドとは何ですか?

オーバーライド手段サブクラスは、スーパークラスにおけるインスタンスメソッドと同じシグネチャと(共変タイプを含む)戻り型とインスタンスメソッドを定義していました。その場合、スーパークラスのメソッドはサブクラスによってオーバーライド(置き換え)されます。 実行されるメソッドのバージョンは、を呼び出すために使用されるオブジェクトによって決定されるになります。 メソッドを呼び出すために使用される参照変数のタイプによって決定されることはありません。

なぜ静的メソッドをオーバーライドできないのですか?

、静的メソッドが静的に解決されているため(すなわち、コンパイル時に)それらが呼び出されるクラスに基づいてではなく、動的に解決多形オブジェクトの実行時の型に基づいてインスタンスメソッドと同様に。

静的メソッドにはどのようにアクセスする必要がありますか?

静的メソッドは静的な方法でアクセスする必要があります。すなわち、インスタンスを使用するのではなく、クラス自体の名前によって行われる。ここで

はオーバーライドと隠ぺいのための短いデモです:foofooのバージョンが呼び出されたので、クラスメソッドであるため、

class Super 
{ 
    public static void foo(){System.out.println("I am foo in Super");} 
    public void bar(){System.out.println("I am bar in Super");} 
} 
class Child extends Super 
{ 
    public static void foo(){System.out.println("I am foo in Child");}//Hiding 
    public void bar(){System.out.println("I am bar in Child");}//Overriding 
    public static void main(String[] args) 
    { 
    Super sup = new Child();//Child object is reference by the variable of type Super 
    Child child = new Child();//Child object is referenced by the variable of type Child 
    sup.foo();//It will call the method of Super. 
    child.foo();//It will call the method of Child. 

    sup.bar();//It will call the method of Child. 
    child.bar();//It will call the method of Child again. 
    } 
} 

出力が指定されているように、明らかに

I am foo in Super 
I am foo in Child 
I am bar in Child 
I am bar in Child 

ありますChildのオブジェクトを参照する参照変数のタイプ(つまり、スーパーまたはチャイルド)によって決定されます。変数がSuperで参照される場合はfooSuperが呼び出されます。また、Childという変数で参照されている場合は、fooChildが呼び出されます。barので一方

が呼び出さbarのバージョンは、単にそれを呼び出すために使用されているオブジェクト(すなわちChild)によって決定されるように、インスタンスメソッドです。どちらの参照変数(SuperまたはChild)が呼び出されても、呼び出されるメソッドは常にChildです。

関連する問題