2013-05-01 9 views

답변

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 같은 것을 말함으로써 부모 클래스 메소드에 액세스 할 수 있습니까? 그러면 여기서 숨어있는 것은 무엇입니까? 이 함수는 호출 된 함수가 인스턴스가 아닌 참조 변수와 연결된 사실이라는 사실을 다시 강조합니다. 여전히이 용어에 대한 구체적인 필요성을 파악할 수 없다.'super'는'this'와 같이 정적 컨텍스트에서는 사용할 수 없습니다. – JATMON

+7

. 하지만 Cat.foo()에서 Animal.foo()를 호출 할 수는 있지만 두 메소드는 이름과 서명을 제외하고 실제로는 공통점이 없습니다. 숨기기는 재정의와 구별되는 데 사용됩니다. 그러나 메소드 숨기기는 실제로 유용하지는 않지만 메소드 오버라이드는 객체 지향 디자인의 핵심 부분 중 하나입니다. –

1

예를 들어 수퍼 클래스에서 인스턴스 메소드를 대체 할 수 있지만 정적은 오버라이드 할 수 없습니다.

부모 클래스에는 Foo라는 정적 메서드가 있고 하위 클래스에는 Foo라는 정적 메서드도 있습니다.

또 다른 시나리오는 부모 클래스에 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

먼저?

방법 숨어 서브 클래스의 수퍼 클래스의 메소드와 동일한 특성을 가진 클래스 방법을 정의한 것을 의미한다. 이 경우 수퍼 클래스의 메서드는 서브 클래스에 의해 숨겨집니다. 실행되는 메서드의 버전은 이 아니며을 호출하는 데 사용되는 개체에 의해 결정됩니다. 실제로 메서드를 호출하는 데 사용되는 참조 변수 유형에 의해 결정됩니다.

오버라이드 란 무엇입니까?

방법 오버라이드 수단은 서브 클래스는 상위 클래스의 인스턴스 메소드와 같은 서명 (공변 형 포함) 반환형 함께 인스턴스 메소드를 정의했다. 이 경우 슈퍼 클래스의 메소드는 서브 클래스에 의해 대체 (대체)됩니다. 실행되는 메서드의 버전은을 호출하는 데 사용되는 개체에 의해 결정되는이됩니다. 메서드를 호출하는 데 사용되는 참조 변수의 유형에 의해 결정되지 않습니다.

왜 정적 메서드를 재정의 할 수 없습니까?

, 정적 메서드는 정적으로 해결하기 때문에 (즉, 컴파일시)가 호출되는 클래스를 기반으로하지 동적으로 해결 다형 객체의 실행시의 형태를 기반으로 인스턴스 메서드의 경우와 같이 .

정적 메서드는 어떻게 액세스해야합니까?

정적 메서드는 정적 방법으로 액세스해야합니다. 인스턴스를 사용하지 않고 클래스 자체의 이름으로 여기

메소드 오버라이드 및 숨기기에 대한 짧은 데모입니다 : 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입니다.