poly(여러개) + morphism(형태) = 다형성(polymorphism)
즉 다형성이란, 하나의 객체가 여러가지 형태를 가질 수 있다는 뜻이다.
자바에서의 다형성이란, 한 타입의 참조변수를 통해 여러타입의 인스턴스를 참조할 수 있도록 한 것이다.
//참조변수의 다형성 예시
class Friend {
public void friendInfo() {
System.out.println("나는 당신의 친구입니다.");
}
}
class BoyFriend extends Friend {
public void friendInfo() {
System.out.println("나는 당신의 남자친구입니다.");
}
}
class GirlFriend extends Friend {
public void friendInfo() {
System.out.println("나는 당신의 여자친구입니다.");
}
}
public class FriendTest {
public static void main(String[] args) {
Friend friend = new Friend(); // 객체 타입과 참조변수 타입의 일치
BoyFriend boyfriend = new BoyFriend();
Friend girlfriend = new GirlFriend(); // 객체 타입과 참조변수 타입의 불일치
friend.friendInfo();
boyfriend.friendInfo();
girlfriend.friendInfo();
}
}
// 출력값
나는 당신의 친구입니다.
나는 당신의 남자친구입니다.
나는 당신의 여자친구입니다.
Friend girlfriend = new GirlFriend();
위의 코드를 살펴보자.
상위클래스의 참조변수 타입으로 지정한 뒤 하위클래스의 인스턴스를 생성[new 생성자()]하여 변수에 할당[참조변수 =] 한 경우이다.
원래라면 타입을 일치시키기 위해 GirlFriend를 참조변수 타입으로 지정해주어야 하지만 상위클래스 Friend를 타입으로 지정해주고 있다.
이 경우, 상위클래스를 참조변수의 타입으로 지정했기 때문에 참조변수가 사용할 수 있는 멤버(이/필/메)의 개수는 상위클래스의 멤버의 수가 된다.
💡 다형성의 핵심
상위 클래스 타입의 참조변수로 하위클래스의 객체를 참조하는 것. 즉, 하나의 객체가 여러 가지 형태를 가질 수 있는 성질을 의미한다.
참조변수의 타입변환이란 사용할 수 있는 멤버의 개수를 조절하는 것을 의미한다.
- 상속관계일 때만 : 상위클래스-하위클래스 사이에만 타입변환이 가능하다.
- 업캐스팅 (하위클래스타입 -> 상위클래스타입)은 형변환 연산자 괄호()를 생략할 수 있다.
- 다운캐스팅 (상위클래스타입 -> 하위클래스타입)은 반드시 형변환 연산자 괄호()를 명시해야한다.
public class VehicleTest {
public static void main(String[] args) {
Car car = new Car();
Vehicle vehicle = (Vehicle) car; // 상위 클래스 Vehicle 타입으로 변환(생략 가능)
Car car2 = (Car) vehicle; // 하위 클래스 Car타입으로 변환(생략 불가능)
MotorBike motorBike = (MotorBike) car; // 상속관계가 아니므로 타입 변환 불가 -> 에러발생
}
}
class Vehicle {
String model;
String color;
int wheels;
void startEngine() {
System.out.println("시동 걸기");
}
class Car extends Vehicle {
void giveRide() {
System.out.println("다른 사람 태우기");
}
}
class MotorBike extends Vehicle {
void performance() {
System.out.println("묘기 부리기");
}
}
참조변수의 타입변환은 서로 상속 관계에 있는 관계에서는 양방향으로 자유롭게 수행될 수 있으나, 상위 클래스로의 타입 변환이냐(괄호 생략 가능) 아니면 하위 클래스로의 타입 변환이냐(괄호 생략 불가)에 따라서 약간의 차이가 있다.
상속이 다형성의 다양한 설계 유연성을 제공함에도 불구하고 무분별한 상속의 사용은 권장하지 않는다.
객체 지향 프로그래밍에서는 HAS-A와 IS-A관계를 나눈다.
HAS-A(포함관계)는 소속 관계이며 예를 들어 ‘직원은 월급을 받는다’란 것 처럼 월급 속성이 있습니다. 월급은 객체이고 클래스의 멤버로 적합하다.
IS-A(상속관계)관계는 ‘사람은 동물이다.’ 라는 명제 처럼 동물 클래스에 사람이 속해있기 때문에 class 사람 extends 동물 과 같이 상속관계(확장)에 있다.
기술적으로 보면 HAS-A는 멤버 변수의 관계고, IS-A는 생성자 부터 메소드까지 포괄해서 확장하는 관계다.