[자바의 정석] 다형성

강신현·2022년 5월 26일
0

자바의 정석

목록 보기
13/15

✅ 다형성 ✅ Up/Down casting ✅ instanceof

다형성

  • 다형성 : 여러 가지 형태를 가질 수 있는 능력
  • 자바에서는 한 타입의 참조변수로 여러 타입의 객체를 참조할 수 있도록 함으로써 다형성을 구현하였다.

조상클래스 타입의 참조변수로 자손클래스의 인스턴스를 참조할 수 있도록 하였다. (반대는 불가능)

// TV : 조상클래스
// CaptionTV : 자손클래스

TV t = new CaptionTV(); // 조상 타입의 참조변수로 자손 인스턴스를 참조
  • 실제 인스턴스가 CaptionTV라 할지라도, 참조변수 t로는 CaptionTV 인스턴스의 모든 멤버를 사용할 수 없다.
  • 즉, 참조변수의 타입에 따라 사용할 수 있는 멤버의 개수가 달라진다.
  • 참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.

참조변수의 형변환

서로 상속관계에 있는 클래스 사이에서만 참조변수의 형변환이 가능하다.
형변환을 통해, 참조하고 있는 인스턴스에서 사용할 수 있는 멤버의 범위(개수)를 조절한다.

- Up-casting

  • 자손타입 -> 조상타입
  • 인스턴스에서 사용할 수 있는 멤버의 범위가 작아진다.
  • 형변환 생략가능

- Down-casting

  • 조상타입 -> 자손타입
  • 인스턴스에서 사용할 수 있는 멤버의 범위가 커진다.
  • 형변환 생략불가
package CastingTest1;

public class CastingTest1 {

	public static void main(String[] args) {
		Car car = null;
		FireEngine fe = new FireEngine();
		FireEngine fe2 = null;
		
		fe.water();
		
		// Up-casting
		car = fe; // 형변환 생략 가능 
		// car.water(); (X) // Car 타입의 참조변수로는 water()를 호출할 수 없음.
		
		// Down-casting
		fe2 = (FireEngine)car; // 형변환 생략 불가능 
		fe2.water();
	}

}

class Car{
	String color;
	int door;
	
	void drive() {
		System.out.println("drive");
	}
	
	void stop() {
		System.out.println("stop");
	}
}

class FireEngine extends Car{
	void water() {
		System.out.println("water");
	}
}

instanceof 연산자

  • 조상타입의 참조변수로 자손타입의 인스턴스를 참조할 수 있기 때문에, 참조변수의 타입과 인스턴스의 타입이 항상 일치하지는 않는다.
  • 조상타입의 참조변수로는 실제 인스턴스의 멤버들을 모두 사용할 수 없기 때문에, 실제 인스턴스와 같은 타입의 참조변수로 형변환을 해야만 인스턴스의 모든 멤버들을 사용할 수 있다.

참조변수가 참조하고 있는 인스턴스의 실제 타입을 판별하여 true, false로 리턴한다.
연산결과 true : 참조변수가 검사한 타입으로 형변환이 가능하다는 것을 뜻한다.

if(c instanceof FireEngine){
	FireEngine fe = (FireEngine)c;
}

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

멤버변수가 조상 클래스와 자손 클래스에 중복으로 정의된 경우,
조상타입의 참조변수를 사용했을 때는 조상 클래스에 선언된 멤버변수가 사용되고,
자손타입의 참조변수를 사용했을 때는 자손 클래스에 선언된 멤버변수가 사용됨

package BindingTest;

public class BindingTest {

	public static void main(String[] args) {
		Parent p = new Child(); // 조상타입의 참조변수를 사용
		Child c = new Child(); // 자손타입의 참조변수를 사용
		
		System.out.println("p.x = " + p.x);
		p.method();
		
		System.out.println("c.x = " + c.x);
		c.method();
	}

}

class Parent{
	int x = 100;
	
	void method() {
		System.out.println("Parent Method");
	}
}

class Child extends Parent{
	int x = 200;
	
	void method() {
		System.out.println("Child Method");
	}
}

->
p.x = 100
Child Method
c.x = 200
Child Method

매개변수의 다형성

참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.

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) {
		money = money - t.price;
		bonuspoint = bonuspoint + t.bonuspoint;
	}
	void buy(Computer c) {
		money = money - c.price;
		bonuspoint = bonuspoint + c.bonuspoint;
	}
	void buy(Audio a) {
		money = money - a.price;
		bonuspoint = bonuspoint + a.bonuspoint;
	}
}

다른 제품들도 구입하는 경우들을 모두 고려하여 메서드를 제품의 종류마다 만들어주는 것은 비효율적이다.
따라서 참조형 매개변수는 메서드 호출시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨준다는 것(매개변수의 다형성)을 이용한다.

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(Product p) {
		money = money - p.price;
		bonuspoint = bonuspoint + p.bonuspoint;
	}
}

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

조상타입의 참조변수로 자손타입의 객체를 참조하는 것이 가능하므로 아래와 같이 할 수 있다.

Product p1 = new Tv();
Product p2 = new Computer();
Product p3 = new Audio();

위 코드는 참조변수 배열로도 처리할 수 있다.

Product p[] = new Product[3];
p[0] = new Tv();
p[1] = new Computer();
p[2] = new Audio();
profile
땅콩의 모험 (server)

0개의 댓글