Search

다형성

다형성 (Polymorphism)

여러가지 형태를 가질 수 있는 능력 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성 구현 (in Java) → 조상 클래스 타입의 참조변수로 자손클래스의 인스턴스 참조 가능
참조변수의 타입에 따라 참조 가능한 멤버 개수가 달라진다!
// Tv와 CaptionTv는 서로 상속 관계 class Tv { boolean power; int channel; void power() { power = !power; } void channelUp() { ++channel; } void channelDown() { --channel; } } class CaptionTv extends Tv { String text; // 캡을 보여주기 위한 문자열 void caption() { } } // 두 클래스의 인스턴스를 생성의 일반적인 경우 Tv t = new Tv(); CaptionTv c = new CaptionTv(); // 상속 관계인 클래스의 경우 조상 타입으로 자손 인스턴스 참조 가능 // Tv타입의 참조변수로 CaptionTv 인스턴스의 모든 멤버 사용 가능 Tv t = new CaptionTv();
Java
참조변수가 사용할 수 있는 멤버 개수는 인스턴스 멤버 개수보다 같거나 적어야 한다!
자손 클래스의 인스턴스로 조상 클래스의 멤버 참조 불가

참조변수의 형변환

기본형 변수와 같이 참조변수도 형변환 가능
서로 상속 관계인 클래스 사이에서만 가능
자손타입 → 조상타입 (Up-casting) : 형변환 생략 가능
조상타입 → 자손 타입 (Down-casting) : 형변환 생략 불가
참조변수간의 형변환캐스트 연산자 사용, ( )안에 변환하고자 하는 타입을 적는다.
class Car { String color; int door; void drive() { System.out.println("drive, Brrrr~"); } void stop() { System.out.println("stop!!!"); } } class FireEngine extends Car { void water() { System.out.println("water!!!"); } class Ambulance extends Car { void siren() { System.out.println("siren~~~"); } } // 상속에서형제 관계가 없기 때문에 자손 클래스끼리 형변환 불가능 FireEngine f; Ambulance a; a = (Ambulance)f; // 에러 f = (FireEngine)a; // 에러 // 조상과 자손 클래스간 형변환 가능 Car car = null; FireEngine fe = new FireEngine(); FireEngine fe2 = null; car = fe; // car = (Car)fe;에서 형변환 생략. 업캐스팅. 자손 -> 조상 fe2 = (FireEngine)car; // 형변환 생략 불가. 다운캐스팅. 조상 -> 자손
Java
참조변수의 형변환은 인스턴스를 변환하는 것이 아니기 떄문에 인스턴스엔 아무런 영향 X
참조변수의 형변환을 통해 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위를 조절
참조변수간 형변환 방식
// 풀 버전 CaptionTv c = new CaptionTv(); Tv t = (Tv)c; // 축약 Tv t = new CaptionTv();
Java
CastingTest1.java
CastingTest2.java
서로 상속 관계에 있는 타입 간의 형변환은 쌍방 자유롭지만, 참조변수가 가리키는 인스턴스의 자손타입으로 형변환은 불가능

instanceof 연산자

참조변수가 참조하고 있는 인스턴스의 실제 타입을 확인하기 위해 사용
주로 조건문에 사용
형식 : 참조변수 instanceof 타입(클래스명)
연산결과로 boolean 값 반환
true : 참조변수가 검사한 타입으로 형변환 가능하다는 뜻
void doWork(Car c) { // Car타입의 참조변수 c를 매개변수로 하는 메소드 if (c instanceof FireEngine) { // 참조변수 c가 가리키는 인스턴스 타입 체크 FireEngine fe = (FireEngine)c; fe.water(); ... } else if (c instanceof Ambulance) { Ambulance a = (Ambulance)c; a.siren(); ... } ... }
Java
조상타입의 참조변수로 자손타입 인스턴스 참조가 가능하기 떄문에, 참조변수의 타입과 인스턴스의 타입이 항상 일치하지 않음 → 조상타입의 참조변수로 인스턴스의 멤버들 모두 사용이 불가능할 수 있기 때문에, 실제 인스턴스와 같은 타입의 참조변수로의 형변환 필요
instanceof의 연산 결과가 true라는 건 검사한 타입으로 형변환이 가능하다는 뜻
InstanceofTest.java

참조변수와 인스턴스의 연결

멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우
조상타입의 참조변수 사용조상 클래스에 선언된 멤버변수 사용
자손타입의 참조변수 사용자손 클래스에 선언된 멤버변수 사용
BindingTest.java
중복으로 정의된 경우가 아니라면 모두 같은 변수 사용
BindingTest2.java
인스턴스 변수에 직접 접근하면 참조변수의 타입에 따라 사용되는 인스턴스변수가 달라질 수 있으므로 주의
(일반적으론 멤버변수들을 private으로 직접적인 접근은 제한하고, 메소드를 통해서 접근)
BindingTest3.java

매개변수의 다형성

class Product { int price; int bonusPoint; } class Tv extends Product { } class Computer extends Product { } class Audio extends Product { } class Buyer { int money = 1000; int bonusPoint = 0; void buy(Tv t) { // Tv를 살 경우 // 기존 보유 금액에서 가격 차감 money = money - t.price; // 보너스 점수는 쌓임 bonusPoint = bonusPoint + t.bonusPoint; } // 물건마다 메소드를 따로 정하기 번거로우니 다형성을 적용 void buy(Product p) { // Product 타입의 자손타입의 참조변수는 어느 것이든 매개변수 가능 money = money - p.price; bonusPoint = bonusPoint + p.bonusPoint; } }
Java
PolyArgumentTest.java

매개변수 다형성의 또다른 예시 : Print(Object obj) 메소드

다양한 타입의 print() 메소드가 각각 정의되어 있지만, print() 메소드 하나로 통일해서 매개변수만 바꿔서 사용 가능

여러 종류의 객체를 배열로 다루기

PolyArgumentTest2.java
배열의 크기를 관리해주는 Vector 클래스를 사용하면 유용
Vector() : 10개 객체를 저장가능한 Vector 인스턴스 생성 10개를 넘어가면 자동으로 크기 증가
boolean add(Obejct o) : Vector에 객체 추가. 성공하면 true, 실패하면 false
boolean remove(Obejct o) : Vector에서 객체 삭제. 성공하면 true, 실패하면 false
boolean isEmpty() : Vector가 비었는지 검사
Object get(int index) : 지정된 위치(index) 반환. 반환타입이 Object가 아니면 형변환 필요
int size() : Vector에 저장된 객체의 개수 반환
PolyArgumentTest3.java

참고 자료