다형성이란?
상위 클래스가 동일한 메시지로 하위 클래스들을 서로 다르게 동작시키는 객체 지향 원리
자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 프로그램적으로 구현.
class TV {
protected int size;
public TV(int size) {
this.size = size;
}
protected int getSize() {
return size;
}
}
class ColorTV extends TV {
protected int resolution;
public ColorTV(int size, int resolution) {
super(size);
this.resolution = resolution;
}
public void printProperty() {
System.out.println(size + " 인치 " + resolution + " 해상도");
}
class SmartTV extends TV {
String text;
public SmartTV(int size) {
super(size);
}
void caption() {
}
}
Java
복사
Upcasting
부모 클래스 변수로 자식 클래스 객체를 참조할 수 있다.
이것을 업캐스팅(upcasting, 상형 형변환)이라고 한다.
public static void main(String[] args) {
TV myColorTV = new ColorTV(32, 1024); // 조상 타입 참조변수로 자손 타입 인스턴스 참조
TV mySmartTV = new mySmartTV(32, 1024); // 조상 타입 참조변수로 자손 타입 인스턴스 참조
}
Java
복사
이처럼 인스턴스의 타입과 참조변수의 타입이 일치하는 것이 보통이지만, Tv와 ColorTv클래스가 서로 상속관계이 있을 경우, 다음과 같이 조상 클래스 타입의 참조변수로 자손 클래스의 인스턴스를 참조하는 것도 가능하다.
Tv타입의 참조변수로는 SmartTV인스턴스 중에서 Tv클래스의 멤버들 (상속받은 멤버포함)만 사용할 수 있다. 따라서 생성된 SmartTv인스턴스의 멤버 중에서 Tv클래스에 정의되지 않은 멤버, text와 caption()은 참조변수 t로 사용이 불가능하다. 즉, t.text또는 t.caption()와 같이 할 수 없다는 것이다. 둘 다 같은 타입의 인스턴스지만 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.
조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있다.
반대로 자손타입의 참조변수로 조상타입의 인스턴스를 참조할 수는 없다.
오버라이딩
조상 클래스로부터 상속받은 메서드의 내용을 변경하는 것을 오버라이딩이라고 한다
class Exployee {
protected int salary;
public Exployee() {
salary = 3000000;
}
public int getSalary() {
return salary;
}
public void setSalary(int salary) {
this.salary = salary;
}
}
class Manager extends Exployee {
public Manager() {
super.setSalary(super.getSalary() + 2000000);
}
@Override
public int getSalary() {
return super.getSalary();
}
}
Java
복사
오버라이딩의 조건
오버라이딩은 메서드의 내용만을 새로 작성하는 것이므로 메서드의 선언부(메서드 이름, 매개변수, 반환타입)는 조상의 것과 완전히 일치해야 한다.
다만 접근 제어자(access modifier)와 예외(exception)는 제한된 조건 하에서만 다르게 변경할 수 있다.
1.
접근 제어자는 조상 클래스의 메서드보다 좁은 범위로 변경 할 수 없다.
만일 조상 클래스에 정의된 메서드의 접근 제어자가 protected라면, 이를 오버라이딩하는 자손 클래스의 메서드는 접근 제어자가 protected나 public이어야 한다.
2.
조상 클래스의 메서드보다 많은 수의 예외를 선언할 수 있다.
조상 클래스의 메서드를 자손 클래스에서 오버라이딩 할 때
1. 선언부가 조상 클래스의 메서드와 일치해야 한다.
2. 접근 제어자를 조상 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
3. 예외는 조상 클래스의 메서드보다 많이 선언할 수 없다.
오버라이딩된 메소드 호출
인스턴스 내부에서 키워드 super를 이용해 호출
class Cake {
public void yummy() {
System.out.println("Yummy Cake");
}
}
class CheeseCake extends Cake {
public void yummy() {
super.yummy();
System.out.println("Yummy Cheese Cake");
}
public void tasty() {
super.yummy();
System.out.println("Yummy Tasty Cake");
}
}
Java
복사
전승환_0926
업캐스팅 & 다운캐스팅
다형성의 핵심적인 특징이다.
1.
업캐스팅: 상속 관계에 있는 두 객체 중 Child Object(자식 객체)를 사용하여 부모 객체(Parent Object)를 선언 및 생성할 수 있는 것을 말한다.
예시 코드
코드 설명
형변환을 위해 명시해야 하는 괄호는 생략 가능하다
그렇다면 다음 코드의 결과는 어떨까? (왼쪽 클릭)
결과 보기
2.
다운캐스팅: 업캐스팅과 반대로 Parent Object(부모 객체)를 이용해 Child Object(자식 객체)를 형변환 하는 것을 말한다.
업캐스팅과는 다르게 괄호를 반드시 명시해야 한다 → 형태: (자식 객체 이름) 부모 객체
다형성의 활용
다형성을 활용하면 보다 편리하고 효율적으로 코드를 작성할 수 있다. 예로, 배열을 만들 때, 하나만의 부모 클래스 타입을 사용해 선언하여도 모든 자식 클래스를 배열의 원소로 사용할 수 있게 된다.
코드 예시
결과 보기
배열 외에도 프린트 함수나 다른 메서드에서도 유용하게 사용 가능하다!