Java에서 메소드 숨김이란 무엇입니까? JavaDoc 설명조차도 혼란 스럽습니다.
Javadoc 말한다 :
호출되는 숨겨진 메서드의 버전은 수퍼 클래스에있는 버전이고 호출되는 재정의 된 메서드의 버전은 하위 클래스에있는 버전입니다.
나에게 종을 울리지 않습니다. 이것의 의미를 보여주는 명확한 예는 높이 평가 될 것입니다.
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 because the declared type of a is 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 d 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
먼저 방법 숨기기 란 무엇을 의미합니까?
메서드 숨김은 하위 클래스가 수퍼 클래스 의 클래스 메서드 와 동일한 서명을 가진 클래스 메서드 를 정의했음을 의미 합니다. 이 경우 수퍼 클래스의 메서드는 하위 클래스에 의해 숨겨집니다. 그것은 그 의미 : 것이다 실행되는 방법의 버전 NOT 를 호출하는 데 사용되는 객체에 의해 결정될 수를 . 실제로 메서드를 호출하는 데 사용되는 참조 변수 의 유형에 따라 결정됩니다 .
메서드 재정의 란 무엇을 의미합니까?
메서드 재정의는 서브 클래스가 슈퍼 클래스 의 인스턴스 메서드 와 동일한 서명 및 반환 유형 (공변 유형 포함)을 가진 인스턴스 메서드 를 정의했음을 의미 합니다. 이 경우 수퍼 클래스의 메소드는 서브 클래스에 의해 대체 (대체)됩니다. : 그것은 것을 의미 실행되는 방법의 버전이 될 것이다 를 호출하는데 사용되는 목적에 따라 결정 . 메서드를 호출하는 데 사용되는 참조 변수 유형에 의해 결정되지 않습니다 .
정적 메서드를 재정의 할 수없는 이유는 무엇입니까?
왜냐하면 정적 메서드는 호출되는 클래스를 기반으로 정적으로 (즉, 컴파일 타임에) 해결되며, 객체의 런타임 유형에 따라 다형성으로 해결되는 인스턴스 메서드의 경우와 같이 동적이 아닙니다.
정적 메서드에 어떻게 액세스해야합니까?
정적 메서드는 정적 방식으로 액세스해야합니다. 즉, 인스턴스를 사용하는 것이 아니라 클래스 자체의 이름으로.
다음은 메서드 재정의 및 숨기기에 대한 짧은 데모입니다.
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
분명히 지정된대로 foo
는 클래스 메서드이므로 foo
호출 된 버전은 의 개체를 참조하는 참조 변수 유형 (예 : Super 또는 Child)에 의해 결정됩니다 Child
. Super
변수에 의해 참조되면 foo
of Super
가 호출됩니다. 그리고 Child
변수에 의해 참조되면 foo
of Child
가 호출됩니다.
반면 ,
Since bar
는 인스턴스 메서드이므로 bar
호출 된 버전은 호출에 사용되는 객체 (예 :)에 의해서만 결정됩니다 Child
. 어떤 참조 변수 ( Super
또는 Child
)가 호출 되든 상관없이 호출 될 메서드는 항상입니다 Child
.
메서드 를 덮어 쓴다는 것은 파생 클래스의 개체에서 메서드가 호출 될 때마다 새 구현이 호출됨을 의미합니다.
메서드 를 숨기는 것은이 클래스의 범위 (즉, 메서드의 본문에서 또는이 클래스의 이름으로 정규화 된 경우)에서 해당 이름에 대한 정규화되지 않은 호출이 이제 완전히 다른 함수를 호출 하여 자격이 필요함을 의미합니다. 부모 클래스에서 동일한 이름의 정적 메서드에 액세스합니다 .
자세한 설명 Java 상속 : 덮어 쓰기 또는 숨겨진 메서드
서브 클래스가 수퍼 클래스의 클래스 메소드와 동일한 시그니처를 사용하여 클래스 메소드를 정의하는 경우 서브 클래스의 메소드는 수퍼 클래스의 메소드를 숨 깁니다.
숨겨진 방법은 정적 컨텍스트에 있다고 생각합니다. 컴파일 타임에 컴파일러가 메서드 호출을 확인하기 때문에 정적 메서드는 그 자체로 재정의되지 않습니다. 따라서 부모 클래스에있는 것과 동일한 시그니처를 사용하여 기본 클래스에 정적 메서드를 정의하면 하위 클래스의 메서드가 수퍼 클래스에서 상속 된 메서드를 숨 깁니다.
class Foo {
public static void method() {
System.out.println("in Foo");
}
}
class Bar extends Foo {
public static void method() {
System.out.println("in Bar");
}
}
예를 들어, 슈퍼 클래스에서 인스턴스 메서드를 재정의 할 수 있지만 정적이 아닙니다.
Hiding is Parent 클래스에는 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; }
}
class P
{
public static void m1()
{
System.out.println("Parent");
}
}
class C extends P
{
public static void m1()
{
System.out.println("Child");
}
}
class Test{
public static void main(String args[])
{
Parent p=new Parent();//Parent
Child c=new Child(); //Child
Parent p=new Child(); //Parent
}
}
If the both parent and child class method are static the compiler is responsible for method resolution based on reference type
class Parent
{
public void m1()
{
System.out.println("Parent");
}}
class Child extends Parent
{
public void m1()
{
System.out.println("Child")
}
}
class Test
{
public static void main(String args[])
{
Parent p=new Parent(); //Parent
Child c=new Child(); //Child
Parent p=new Child(); //Child
}
}
If both method are not static jvm is responsible for method resolution based on run time object
'Program Tip' 카테고리의 다른 글
모든 줄 바꿈을 제거하고 특정 텍스트 뒤에 추가 (0) | 2020.11.29 |
---|---|
Eclipse에서 Maven 프로젝트를 만들면 "Could not resolve archetype"이 표시됩니다. (0) | 2020.11.29 |
Interface Builder가 drawRect를 재정의하지 않는 IBDesignable 뷰를 렌더링하는 방법이 있습니까? (0) | 2020.11.29 |
Lua 패턴 매칭과 정규 표현식 (0) | 2020.11.28 |
DAO 및 서비스 계층 (JPA / Hibernate + Spring) (0) | 2020.11.28 |