태그 보관물: overriding

overriding

자바 오버라이드 vs 숨기기-혼동 public static void testClassMethod() {

재정의가 Java에서 숨기는 것과 어떻게 다른지 혼란 스럽습니다. 누구든지 이것이 어떻게 다른지에 대한 자세한 내용을 제공 할 수 있습니까? Java Tutorial을 읽었 지만 샘플 코드가 여전히 혼란 스러웠습니다.

더 명확하게 말하자면 재정의를 잘 이해합니다. 내 문제는 하나가 인스턴스 수준에 있고 다른 하나가 클래스 수준에 있다는 사실을 제외하고는 숨어있는 것이 얼마나 다른지 알 수 없다는 것입니다.

Java 튜토리얼 코드 살펴보기 :

public class Animal {
    public static void testClassMethod() {
        System.out.println("Class" + " method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("Instance " + " method in Animal.");
    }
}

그런 다음 하위 클래스가 있습니다 Cat.

public class Cat extends Animal {
    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) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}

그런 다음 그들은 말합니다.

이 프로그램의 출력은 다음과 같습니다.

Animal의 클래스 방법.

Cat의 인스턴스 메서드.

나에게 클래스 testClassMethod()에서 직접 클래스 메서드를 호출하면 클래스에서 메서드가 Animal실행 된다는 사실 Animal은 매우 분명하며 특별한 것은 없습니다. 그런 다음 testInstanceMethod()참조에서 를 호출 myCat하므로 실행 된 메서드가의 인스턴스에있는 메서드라는 것이 다시 분명합니다 Cat.

내가보기에, 콜 숨김은 오버 라이딩과 똑같이 작동하는데, 왜 그렇게 구별합니까? 위의 클래스를 사용하여이 코드를 실행하면 :

Cat.testClassMethod();

나는 얻을 것이다 :
Cat.
그러나 testClassMethod()Cat에서 제거하면 Animal의 클래스 메서드를 얻을 수
있습니다.

이것은 부모와 동일한 서명을 가진 정적 메서드를 하위 클래스에서 거의 재정의하는 것을 보여줍니다.

내가 혼란스럽고 누군가가 빛을 발할 수있는 곳을 분명히하고 있기를 바랍니다. 미리 감사드립니다!



답변

재정의는 기본적으로 후기 바인딩을 지원합니다. 따라서 어떤 메서드가 호출 될지 런타임에 결정됩니다. 비 정적 메서드 용입니다.

숨기기는 다른 모든 멤버 (정적 메서드, 인스턴스 멤버, 정적 멤버)를위한 것입니다. 초기 바인딩을 기반으로합니다. 보다 명확하게 호출하거나 사용할 메서드 또는 멤버는 컴파일 시간에 결정됩니다.

귀하의 예에서 첫 번째 호출 Animal.testClassMethod()static메서드에 대한 호출 이므로 어떤 메서드가 호출 될지 꽤 확실합니다.

두 번째 호출 인 myAnimal.testInstanceMethod()에서는 비 정적 메서드를 호출합니다. 이것이 바로 런타임 다형성이라고 부르는 것입니다. 어떤 메소드를 호출할지 런타임까지 결정되지 않습니다.

자세한 내용은 Overriding Vs Hiding을 참조하십시오 .


답변

정적 메서드는 숨겨지고 비 정적 메서드는 재정의됩니다. 호출이 “something ()”과 “this.something ()”으로 한정되지 않은 경우 차이가 두드러집니다.

나는 정말로 그것을 단어에 적어 놓을 수없는 것처럼 보인다. 그래서 여기에 예가있다.

public class Animal {

    public static void something() {
        System.out.println("animal.something");
    }

    public void eat() {
        System.out.println("animal.eat");
    }

    public Animal() {
        // This will always call Animal.something(), since it can't be overriden, because it is static.
        something();
        // This will call the eat() defined in overriding classes.
        eat();
    }

}


public class Dog extends Animal {

    public static void something() {
        // This method merely hides Animal.something(), making it uncallable, but does not override it, or alter calls to it in any way.
        System.out.println("dog.something");
    }

    public void eat() {
        // This method overrides eat(), and will affect calls to eat()
        System.out.println("dog.eat");
    }

    public Dog() {
        super();
    }

    public static void main(String[] args) {
        new Dog();
    }

}

산출:

animal.something
dog.eat

답변

이것이 오버라이드와 숨김의 차이점입니다.

  1. 부모 클래스와 자식 클래스의 메서드가 모두 인스턴스 메서드이면 재정의를 호출했습니다.
  2. 부모 클래스와 자식 클래스의 메서드가 모두 정적 메서드 인 경우 숨김이라고합니다.
  3. 한 메서드는 부모에서 정적 일 수없고 자식에서 인스턴스로 사용할 수 없습니다. 반대의 경우도 마찬가지입니다.


답변

내가 귀하의 질문을 제대로 이해했다면 대답은 “이미 무시하고 있습니다”입니다.

“부모와 동일한 이름을 가진 정적 메서드를 하위 클래스에서 작성하는 것이 거의 오버라이드를 수행한다는 것을 보여줍니다.”

슈퍼 클래스의 메서드와 정확히 동일한 이름을 가진 메서드를 서브 클래스에 작성하면 슈퍼 클래스의 메서드가 재정의됩니다. 메서드를 재정의하는 데 @Override 주석이 필요하지 않습니다. 그러나 코드를 더 읽기 쉽게 만들고 컴파일러가 실제로 메서드를 재정의하고 있는지 (예를 들어 하위 클래스 메서드를 잘못 입력하지 않았는지) 확인하도록합니다.


답변

재정의는 인스턴스 메서드에서만 발생합니다. 참조 변수의 유형이 Animal이고 객체가 Cat이면 Cat에서 인스턴스 메서드가 호출됩니다 (이는 재정의 됨). 동일한 acat 객체에 대해 Animal 클래스 메서드가 사용됩니다.

public static void main(String[] args) {
    Animal acat = new Cat();
    acat.testInstanceMethod();
    acat.testClassMethod();

}

출력은 다음과 같습니다.

The instance method in Cat.
Class method in Animal.

답변

public class First {

    public void Overriding(int i) {  /* will be overridden in class Second */ }

    public static void Hiding(int i) {  /* will be hidden in class Second
                                           because it's static */ }
}


public class Second extends First {

    public void Overriding(int i) {  /* overridden here */  }

    public static void Hiding(int i) {  /* hides method in class First
                                           because it's static */ }
}

암기 규칙은 간단합니다. 확장 클래스의 메서드는 static을 void로 변경할 수없고 void를 static으로 변경할 수 없습니다. 컴파일 오류의 원인이됩니다.

그러나 void Name변경 되면 void Name재정의입니다.

그리고 static Name변경 되면 static NameHiding입니다. (메소드를 호출하는 데 사용되는 참조 유형에 따라 하위 클래스의 정적 메서드와 수퍼 클래스 중 하나를 모두 호출 할 수 있습니다.)


답변

이 코드 조각에서는 ‘정적’대신 ‘개인’액세스 한정자를 사용하여 메서드 숨기기와 메서드 재정의의 차이점을 보여줍니다.

class Animal {
// Use 'static' or 'private' access modifiers to see how method hiding work.
private void testInstancePrivateMethod(String source) {
    System.out.println("\tAnimal: instance Private method calling from "+source);
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Private method.");
    testInstancePrivateMethod( Animal.class.getSimpleName() );
}

// Use default, 'protected' or 'public' access modifiers to see  how method overriding work.
protected void testInstanceProtectedMethod(String source) {
    System.out.println("\tAnimal: instance Protected method calling from "+source);
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("\tAnimal: instance Public method with using of Protected method.");
    testInstanceProtectedMethod( Animal.class.getSimpleName() );
  }
}


public class Cat extends Animal {
private void testInstancePrivateMethod(String source) {
    System.out.println("Cat: instance Private method calling from " + source );
}
public void testInstanceMethodUsingPrivateMethodInside() {
    System.out.println("Cat: instance Public method with using of Private method.");
    testInstancePrivateMethod( Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingPrivateMethodInside();
}

protected void testInstanceProtectedMethod(String source) {
    System.out.println("Cat: instance Protected method calling from "+ source );
}
public void testInstanceMethodUsingProtectedMethodInside() {
    System.out.println("Cat: instance Public method with using of Protected method.");
    testInstanceProtectedMethod(Cat.class.getSimpleName());
    System.out.println("Cat: and calling parent after:");
    super.testInstanceMethodUsingProtectedMethodInside();
}

public static void main(String[] args) {
    Cat myCat = new Cat();
    System.out.println("----- Method hiding -------");
    myCat.testInstanceMethodUsingPrivateMethodInside();
    System.out.println("\n----- Method overriding -------");
    myCat.testInstanceMethodUsingProtectedMethodInside();
}
}

산출:

----- Method hiding -------
Cat: instance Public method with using of Private method.
Cat: instance Private method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Private method.
   Animal: instance Private method calling from Animal

----- Method overriding -------
Cat: instance Public method with using of Protected method.
Cat: instance Protected method calling from Cat
Cat: and calling parent after:
   Animal: instance Public method with using of Protected method.
Cat: instance Protected method calling from Animal