컴파일 시점에 메서드 정의와 메서드 호출을 연결하는 방식
실행 시점에 메서드 정의와 메서드 호출을 연결하는 방식 (동적 바인딩)
("다양한 형태") 한 객체가 여러 타입의 객체로 취급될 수 있는 것
다형적 참조 + 메서드 overriding 으로 구현되는 것
Parent poly = new Parent()
Parent poly = new Child()
Parent poly = new GrandChild()
상속관계는 부모 방향으로 찾아 올라갈 수는 있으나 자식방향으로 찾아 내려갈 수는 없다.
poly.childMethod() : ㄴㄴ (캐스팅 필요)
객체 자체가 사실상 자식 인스턴스도 포함할 때, 그 자식에서 override된 메서드로 작동한다; 실행 시점에 객체의 실제 타입에 따라 호출되는 메서드가 결정
public class OverridingMain {
public static void main(String[] args) {
//자식 변수가 자식 인스턴스 참조
Child child = new Child();
System.out.println("Child -> Child");
System.out.println("value = " + child.value);//value = child
child.method(); //childmethod
//부모 변수가 부모 인스턴스 참조
Parent parent = new Parent();
System.out.println("Parent -> Parent");
System.out.println("value = " + parent.value);//value =
parent.method(); //parentmethod
//부모 변수가 자식 인스턴스 참조(다형적 참조)
Parent poly = new Child();
System.out.println("Parent -> Child");
System.out.println("value = " + poly.value); //변수는 오버라이딩X value = parent
poly.method(); //메서드 오버라이딩! : childmethod
Parent poly1 = new Child();
Parent poly2 = new Parent();
Child child1 = (Child) poly1;
Child child2 = (Child) poly2; //runtime error
child1.childMethod(); ((Child) poly1).childMethod();
child2.childMethod() //execute impossible
poly의 타입은 그래로! 자바에선 항상 value-copy!!
poly와 child모두 같은 참조값(e.g. x001)을 참조함
재할당외에는 변수의 내용을 바꿀수 있는 게 없음
memory상에 자식이 존재하지 않는 경우, 실패하는 문제가 생성된다. casting 표시를 항상 해줘야 한다.
Child child = new Child();
Parent parent1 = (Parent) child; //캐스팅 표시
Parent parent2 = child; //권장
객체를 생성하면 해당 타입의 부모타입은 항상 생성되는데,
memory상에 부모가 존재하므로 upcasting은 항상 성공하고, casting 생략도 가능
업캐스팅된 객체는 부모 클래스 타입으로만 참조되기 때문에, 자식 클래스에서 정의된 메서드나 필드에는 접근할 수 없다
instanceOf의 사용public class CastingMain5 {
public static void main(String[] args) {
Parent parent1 = new Parent();
System.out.println("parent1 호출");
call(parent1); // if false
Parent parent2 = new Child();
System.out.println("parent2 호출");
call(parent2); //if true
}
private static void call(Parent parent) {
parent.parentMethod();
if (parent instanceof Child) {
System.out.println("Child 인스턴스 맞음");
Child child = (Child) parent;
child.childMethod();
}
}
}
class Parent {
public static void staticMethod() {
System.out.println("Parent static method");
}
public void instanceMethod() {
System.out.println("Parent instance method");
}
}
class Child extends Parent {
public static void staticMethod() {
System.out.println("Child static method");
}
@Override
public void instanceMethod() {
System.out.println("Child instance method");
}
}
public class Main {
public static void main(String[] args) {
Parent parent = new Child();
// 정적 메서드 호출
parent.staticMethod(); // Parent static method 출력
Parent.staticMethod(); // Parent static method 출력
Child.staticMethod(); // Child static method 출력
// 인스턴스 메서드 호출 (다형성 적용)
parent.instanceMethod(); // Child instance method 출력
}
}
toString()과 다형성]class Parent {
@Override
public String toString() {
return "This is a Parent object";
}
}
class Child extends Parent {
@Override
public String toString() {
return "This is a Child object";
}
}
public class Main {
public static void main(String[] args) {
Parent parent = new Parent();
Parent child = new Child(); // 업캐스팅
// toString() 메서드 호출
System.out.println(parent.toString()); // This is a Parent object
System.out.println(child.toString()); // This is a Child object
}
}
clone()]class Parent {
private int value;
public Parent(int value) {
this.value = value;
}
// 복사 생성자
public Parent(Parent other) {
this.value = other.value;
}
public Parent clone() {
return new Parent(this); // 복사 생성자를 사용하여 객체 복사
}
@Override
public String toString() {
return "Parent{" + "value=" + value + '}';
}
}
class Child extends Parent {
private int extraValue;
public Child(int value, int extraValue) {
super(value);
this.extraValue = extraValue;
}
// 복사 생성자
public Child(Child other) {
super(other); // 부모 클래스의 복사 생성자 호출
this.extraValue = other.extraValue;
}
@Override
public Child clone() {
return new Child(this); // 복사 생성자를 사용하여 객체 복사
}
@Override
public String toString() {
return "Child{" + "value=" + super.toString() + ", extraValue=" + extraValue + '}';
}
}
원래 clone()의 리턴타입은 Object이다. 그런데 리턴타입을 Child로 바뀌었다. 이를 오버라이딩이라 할 수 있는가?
public class Main {
public static void main(String[] args) {
Child original = new Child(10, 20);
Child copy = original.clone(); // 복사 생성자를 사용하여 객체 복사
System.out.println("Original: " + original);
System.out.println("Copy: " + copy);
}
}