20150916
다형성(polymorphism)
다형성을 알기 위해서는 상속에 대한 개념을 알고 있어야 합니다.
우선 자바에서 다형성은 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있게 하므로써 다형성을 나타냅니다.
즉 '여러 가지 형태를 가질 수 있는 능력' 을 의미합니다.
그러니깐 조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조 할 수 있도록 한 겁니다.
car 클래스와 car 클래스를 상속받는 SuperCar 클래스로 예를 들면
아래 코드와 같이
class Car {
int speed = 10;
void speedUp(){
++speed;
System.out.println("car 에서 speed:" + speed + "입니다.");
}
}
class SuperCar extends Car {
int speed = 9;
int model = 2;
boolean booster = false;
void speedUp(){
speed += 2;
System.out.println("supercar에서 speed:" + speed + "입니다.");
}
}
class Test2 {
public static void main(String[] args) {
Car c = new Car();
SuperCar sc = new SuperCar();
Car c2 = new SuperCar();
System.out.println(sc.model); //2 출력됨
// System.out.println(c2.model); // 오류남 변수 model를 사용 할 수 없다.
System.out.println(c.speed); //10 이 출력됨
System.out.println(sc.speed); // 9 가 출력됨
c.speedUp(); //car 에서 speed:11입니다. 가 출렴됨
c2.speedUp(); //supercar에서 speed:12입니다. 가 출력됨
}
}
Car 클래스 와 SuperCar 클래스 두 클래스의 인스턴스를 생성하고 사용하기 위해서 24번 25번 줄처럼 Car c = new Car(); 이런식으로 인스턴스 타입과 참조변수의 타입을 일치해서 사용하는건 아시죠? 그런데 여기서 Car 클래스와 SuperCar 클래스 처럼 서로 상속 관계는 Car c = new SuperCar(); 이런식으로 참조가 가능합니다.
그럼 Car c = new Car(); 와 Car c = new SuperCar(); 의 차이를 설명하자면
왼쪽의 참조변수 타입이 가지고 있는 맴버 변수만 사용이 가능합니다. 쉽게 말해서
car 클래스 맴버의 수는 2가지를 가지고 있고 CarSuperCar클래스는 상속받은 2개 와 자신이 가지고 있는 int model, boolean booster 를 총 더한 4가지고 가지고 있습니다.
Car c = new SuperCar(); 를 예를 들면 참조변수가 c 는 Car 클래스가 가지고 있는 맴버변수 2개만 사용 가능합니다. 그래서 car 는 가지고 있지 못한 SuperCar 의 변수는 사용을 할 수 없습니다.
25번 26번 줄에서 같은 인스턴스로 만들었지만 다른 참조변수 인 sc 와 c2 를 28번과 29번 줄에서 출력해보면 29번 줄은 참조변수 타입이 Car 라서 SuperCar 가 가지고 있는 model 변수를 사용 할 수 없어요. (오류가 납니다.)
그리고 25번과 26번 차이처럼 같은 부모클래스와 자식클래스가 둘다 가지고 있는 맴버변수는 참조변수 클래스에 있는 변수를 사용합니다.
하지만 31번과 32번 차이처럼 같은 부모클래스와 자식클래스가 둘다 가지고 있는 맴버함수는 좀 더 구체화(오버 라이딩)된 자식클래스의 함수를 사용합니다.
반대로 SuperCar sc = new Car(); 는 사용 할 수 없습니다.
위에서 설명 했듯이 참조변수의 타입 맴버 수 만 사용 할 수 있다고 했는데 이런 경우가 되면 사용 할 수 있는 범위중에서 사용 못하는 멤버가 들어가기 때문에 오류가 납니다.
예) sc.model 참조변수 타입 맴버에는 model 변수도 사용 가능 해야 하지만 인스턴스인 car 에는 model 변수가 없기 때문입니다.
참조변수가 사용할 수 있는 맴버 수 는 인스턴스의 개수보다 같거나 작아야 합니다.
참조변수의 형변환
서로 상속관계인 클래스 사이에서는 참조변수도 형변환이 가능합니다.
자손 타입 -> 조상타입 (Up - casting) : 형변환 생략가능
조상타입 <- 자손타입 (Down-casting): 형변환 생략불가
아래 코드에서 처럼
class Car {
.....
}
class SuperCar extends Car {
....
}
class Test2 {
public static void main(String[] args) {
Car c = new Car();
SuperCar sc = new SuperCar();
c = sc; //형변환 생략가능
sc = (SuperCar)c; //형변환 생략할 수 없다.
}
}
아래 코드에서 와 같이 car 와 SuperCar 처럼 상속 관계에서는 15번 줄처럼 형변환이 가능하다. 형변환을 하면 인스턴스의 멤버중 사용 할 수 있는 범위가 달라지게 됩니다.
sc 의 참조변수 타입이 SuperCar 라서 superCar 클래스의 변수를 모두 사용 가능한데 c 참조 변수로 형변환을 하게 되면 Car 클래스가 가지고 있는 변수들만 사용 가능합니다.
참조변수 형변환은 참조변수의 타입이 변환되는 것이기 때문에 인스턴스는 변하지 않습니다.