1. 매개변수의 다형성
※ Promotion : 자동 형변환 vs Casting : 명시적 형변환
- promotion은 멤버 변수의 값을 대입할 때 발생하지만, 메서드 호출 시 사용하는 매개변수에도 발생 가능
- 보통 메서드 호출 시 선언부에서 지정한 데이터타입과 일치하는 매개값을 전달하여 호출하지만, 매개변수에 다형성을 적용하면 자식 객체 전달 가능
1) 강제 타입 변환(Type Casting)
→ 부모 타입을 자식 타입으로 변환하는 것
- 부모 타입으로 형 변환이 된 자식 객체만 강제 타입 변환 사용 가능
public class Parent {
public void method1() {
System.out.println("부모측 1번 메서드 호출");
}
public void method2() {
System.out.println("부모측 2번 메서드 호출");
}
}
public class Child extends Parent{
@Override
public void method2() {
System.out.println("자식측에서 재정의한 2번 메서드");
}
public void method3() {
System.out.println("자식만 가지고 있는 3번 메서드");
}
}
public class MainClass1 {
public static void main(String[] args) {
// Promotion이 적용되면 자식클래스에만 정의된 요소 조회 불가능
Parent p = new Child();
p.method1(); // Parent에만 정의된 메서드
p.method2(); // 오버라이딩된 메서드는 타입상관없이 인스턴스 내 자식쪽 호출
//p.method3(); // p 타입 변수로는 자식쪽에만 정의된 요소 호출 불가
System.out.println("-----------------");
}
}
Parent p = new Child;
① 좌변에 부모클래스, 우변에 자식클래스
② 동일한 메서드가 있어야 함 (@Override)
→ 우선순위는 자식쪽에 있음, 즉 부모타입임에도 불구하고 자식쪽 메서드를 호출할 수 있다. → Promotion
public class MainClass1 {
public static void main(String[] args) {
// Promotion이 적용되면 자식클래스에만 정의된 요소 조회 불가능
Parent p = new Child();
p.method1(); // Parent에만 정의된 메서드
p.method2(); // 오버라이딩된 메서드는 타입상관없이 인스턴스 내 자식쪽 호출
//p.method3(); // p 타입 변수로는 자식쪽에만 정의된 요소 호출 불가
System.out.println("------------------------");
Child c = (Child)p; // 부모타입 변수를 자식타입으로 강제형변환(cast)
c.method2(); // 위와 동일하게 자식측 method2 호출
c.method3(); // 형 변환 후에는 자식쪽에만 있는 요소도 호출 가능
Child cc = new Child(); // 애초에 자식타입으로 인스턴스 대입 시에도
cc.method3(); // 자식쪽에만 있는 요소 호출 가능
}
}
Child c = (Child) p;
★ 부모타입 변수로 자식타입 인스턴스 호출 시
① 부모클래스에만 선언된 메서드 : 부모클래스의 메서드로 호출
② 부모클래스, 자식클래스 모두에 선언된 메서드 (오버라이딩) : 자식클래스의 메서드로 호출
③ 자식클래스에만 선언된 메서드 : 부모 타입으로 호출 불가
public class Child2 extends Parent{
@Override
public void method2() {
System.out.println("2번 자식측에서 재정의한 2번 메서드");
}
public void method3() {
System.out.println("2번 자식만 가지고 있는 3번 메서드");
}
}
public class MainClass2 {
public static void main(String[] args) {
// Parent 타입에는 Child, Child2 모두 대입 가능
Parent p1 = new Child(); // 이 부분만 고쳐도 되는 효율성
p1.method2();
// Parent 타입으로는 Child1의 method2도, Child2의 method2도 호출 가능
// method2는 Parent에도 정의되어 있지만, Child와 Child2에서 오버라이딩된 메서드이기 때문에 호출 가능
}
}
public class MainClass2 {
public static void main(String[] args) {
// Parent 타입에는 Child, Child2 모두 대입 가능
Parent p1 = new Child2(); // 이 부분만 고쳐도 되는 효율성
p1.method2();
// Parent 타입으로는 Child1의 method2도, Child2의 method2도 호출 가능
// method2는 Parent에도 정의되어 있지만, Child와 Child2에서 오버라이딩된 메서드이기 때문에 호출 가능
}
}
2. instanceof 키워드
→ 객체가 지정한 클래스의 인스턴스인지 아닌지 검사할 때 사용
Person p = new student();
p instanceof Student // true 반환
왼쪽 항의 객체가 오른쪽 항 클래스의 인스턴스, 즉 오른쪽 항의 객체가 생성되었다면 true 리턴
public class Human {
public String name;
public int age;
public Human(String name, int age) {
this.name = name;
this.age = age;
}
public Human() {
this("noname", 0);
// this.name = "noname";
// this.age = 0;
}
public void showInfo() {
System.out.println("이름: " + this.name);
System.out.println("나이: " + this.age);
System.out.println("---------------");
}
}
public class Student extends Human {
public Student(String name, int age) {
super(name, age);
}
}
public class Cat {
private String name;
private int age;
public Cat(String name, int age) {
this.name = name;
this.age = age;
}
public void meow() {
System.out.println("야옹 야옹");
}
}
public class MainClass {
public static void main(String[] args) {
// Human, Student, Cat 인스턴스 생성
Human h1 = new Human("김자바", 20);
h1.showInfo();
Student s1 = new Student("태국인", 19);
s1.showInfo();
Cat c1 = new Cat("룰루", 6);
c1.meow();
System.out.println(h1 instanceof Human); // h1이 Human 기반인가
System.out.println(s1 instanceof Human); // s1이 Human 기반인가
System.out.println(h1 instanceof Student); // h1이 Student 기반인가
System.out.println(s1 instanceof Student); // s1이 Student 기반인가
// 관련이 아예 없는 객체간 비교는 에러 발생
//System.out.println(h1 instanceof Cat);
//System.out.println(s1 instanceof Cat);
}
}