Java 다형성은 어떻게 구현되나요?
C++와 마찬가지로 Java의 다형성은 후기 바인딩 또는 런타임 바인딩을 통해 달성됩니다. 객체가 참조하는 메서드가 호출되면 컴파일러는 참조가 변수가 선언될 때 지정된 유형 객체를 가리키는지 아니면 해당 유형의 하위 클래스 객체를 가리키는지 알 수 없습니다. 따라서 컴파일러는 이 호출에 대해 특정 메서드에 바인딩할 수 없습니다. Java의 RTTI(런타임 유형 식별)를 통해 런타임 시 특정 메서드에만 바인딩될 수 있습니다. 다음은 구체적인 예입니다.
class shape { public void draw() { print("shape"); } } class triangle extends shape { public void draw() { print("triangle"); } } public class Polymorphism { public static void main(String[] args) { shape s=new triangle(); s.draw(); }
결과적으로 삼각형
s은 모양 참조이지만 런타임에는 삼각형 개체이므로 삼각형의 그리기 메서드가 계속 호출됩니다.
Java 다형성의 몇 가지 함정
개인 메서드를 재정의하시겠습니까?
Java에서는 개인 메서드를 재정의할 수 없습니다. 개인 메서드는 하위 클래스에 표시되지 않기 때문에 실제로 이해하기 쉽습니다. 하위 클래스는 상위 클래스의 비공개 메서드를 상속하지 않으며 재정의하지도 않습니다. 따라서 하위 클래스에 있는 동일한 이름의 메서드는 완전히 새로운 메서드입니다.
public class Polymorphism { private void show() { print("show parent"); } public static void main(String[] args) { Polymorphism p=new privateMethod(); p.show(); } } class privateMethod extends Polymorphism { public void show() { print("show derived"); } }
결과는 show parent
필드와 정적 메소드의 다형성입니다.
하위 클래스는 상위 클래스의 비공개 필드를 상속할 수 있습니다. 하위 클래스의 필드도 다형성인가요? 실제 예를 살펴보겠습니다.
class shape { protected int perimeter=1; public void draw() { print("shape"); } public int getPerimeter() { return perimeter; } } class triangle extends shape { int perimeter=3; public void draw() { print("triangle"); } public int getPerimeter() { return perimeter; } public int getSuperPerimeter() { return super.perimeter; } } public class Polymorphism { public static void main(String[] args) { shape s=new triangle(); print("s.perimeter:"+s.perimeter); print("s.getperimeter:"+s.getPerimeter()); triangle t=new triangle(); print("t.perimeter:"+t.perimeter); print("t.getperimeter:"+t.getPerimeter()); print("t.getsuperperimeter:"+t.getSuperPerimeter()); } }
이 연산 결과에는 다음 정보가 포함됩니다.
1. 삼각형 개체가 모양으로 변환된 후 필드에 대한 직접 액세스는 컴파일러에 의해 결정됩니다. 따라서 다형성이 표시되지 않습니다. 1이 반환됩니다.
2. 삼각형 객체를 모양으로 변환한 후 필드에 액세스하는 메서드가 호출되며 런타임 객체 유형 지연 바인딩에 따라 반환되는 값은 3입니다.
3 .t 객체에는 두 개의 경계가 포함되어 있습니다. 하나는 자체에서 가져오고 다른 하나는 상위 클래스에서 가져옵니다. 동시에 필드 이름으로 필드를 호출하면 기본적으로 자체 경계 필드가 반환됩니다. 상위 클래스에서 상속된 필드를 호출하려면 super.perimeter 메서드를 사용하세요.
이러한 상황을 피하기 위해 일반적으로 필드를 비공개로 선언합니다(하위 클래스는 상속할 수 없음). 동시에 필드와 동일한 이름을 선언하지 않는 것이 가장 좋습니다. 상위 클래스에서 상속됩니다.
정적 메서드에는 다형성이 없습니다. 왜냐하면 정적 메서드는 클래스에 바인딩되어 있고 특정 유형을 알 필요가 없기 때문입니다.
생성자 다형성?
생성자에는 다형성이 없습니다. 왜냐하면 생성 방법 자체가 정적 방법이기 때문입니다(그렇지 않으면 닭과 달걀, 달걀 낳기-닭 주기에 빠지게 됩니다). 문제를 소개하기 위해 먼저 생성자가 호출되는 순서를 살펴보겠습니다.
1. 이 객체에 할당된 저장 공간은 0으로 초기화됩니다(객체는 null로 초기화됩니다).
2. 상위 클래스의 생성자가 호출됩니다(이렇게 하면 하위 클래스의 생성자에서 필드에 액세스할 수 있습니다). )
3. 멤버 변수 초기화
4. 하위 클래스의 생성자 호출
이제 두 번째 단계에서 상위 클래스의 생성자에서 특정 메서드를 호출한다고 가정합니다. 방법 다형성? 구체적인 예를 살펴보겠습니다.
class shape { protected int perimeter=1; public shape() { draw(); print("shape created"); } public void draw() { print("draw shape "+perimeter); } } class triangle extends shape { int perimeter=3; public triangle() { print("triangle created"); } public void draw() { print("draw triangle "+perimeter); } public int getPerimeter() { return perimeter; } } public class Polymorphism { public static void main(String[] args) { shape s=new triangle(); } }
비록 삼각형 객체가 아직 생성되지 않았지만 그리기 메서드는 여전히 삼각형의 그리기 메서드에 동적으로 바인딩되어 있음을 알 수 있습니다. 또한 둘레 값이 3이 아닌 0으로 초기화되었음을 확인하세요.
결과적으로 삼각형 객체가 초기화되기 전에 해당 객체의 필드에 액세스하게 됩니다. 따라서 실제 응용에서는 생성자에서 다른 메소드 호출을 피하거나, 프라이빗 메소드만 호출해야 합니다(상속되지 않으므로 이런 문제는 발생하지 않습니다)
자바 다형성 사용 주의사항 관련 더보기 기사를 보려면 PHP 중국어 웹사이트에 주목하세요!