반응형
# 목적
: 학습을 위한 다형성 개념 정리
다형성(polymorphism)이란?
: 여러 가지 형태를 가질 수 있는 능력,
조상 타입 참조 변수로 자손 타입 객체를 다루는 것.
다형성은 백마디 말보다 코드로 보는 게 더 이해하기 쉽다.
작성한 예시의 주석을 참고하며 알아보자.
1. 기본 예시
class Tv {
boolean power; // 전원상태(on/off)
int channel; // 채널
void power() { power = !power; }
void channelUp() { ++channel; }
void channelDown() { --channel; }
}
class SmartTv extends Tv {
String text; // 캡션(자막)을 보여주기 위한 문자열
void caption() { /* 내용생략 */ }
}
public class Polymorphsim {
Tv t = new SmartTv(); // 타입 불일치하지만 가능 -> 다형성
//: Tv 리모컨(조상타입의 참조변수)으로 SmartTv 제품(자손타입 객체)을 다룸
}
2. 참조변수의 형변환
: 참조변수(리모컨)을 변경함으로써 사용할 수 있는 멤버의 개수를 조절하는 것
조상, 자손 관계의 참조변수는 서로 형변환 가능 (형제는 불가)
class Car { // 멤버 : 4개
String color;
int door;
void drive() {
System.out.println("drive, Brrrr~");
}
void stop() {
System.out.println("stop");
}
}
class FireEngine extends Car { // 멤버 : 5개 (부모 class인 Car의 멤버까지 사용 가능)
void water() {
System.out.println("water!!!");
}
}
class Ambulance extends Car { /* 생략 */ }
public class Poly {
public static void main(String[] args) {
FireEngine f = new FireEngine();
Car c = f; // 조상인 Car타입으로 형변환(생략가능)
FireEngine f2 = (FireEngine)c; // 자손인 FireEngine타입으로 형변환(생략불가)
// Ambulance a = (Ambulance)f; // Error - 상속관계가 아닌 클래스 간의 형변환 불가
f.water();
// c.water(); // Car타입의 참조변수로는 water() 호출 불가
// - water()는 자식인 FireEngine에 있고, Car에는 없음
}
}
3. instanceof 연산자
: 참조변수의 형변환 가능 여부 확인에 사용 (가능하면 true 반환)
형변환 전에 반드시 instanceof로 확인해야 함
public class Instanceof {
void doWork(Car c) {
if (c instanceof FireEngine) { // 1. 형변환이 가능한지 확인
FireEngine fe = (FireEngine)c; // 2. 형변환
fe.water();
// * 여기서 형변환을 하는 이유 : 인스턴스의 원래 기능을 모두 사용하기 위해.
// - Car타입의 리모컨인 c로는 water() 호출 불가하니, 리모컨을 FireEngine타입으로 바꿔서 호출
}
}
}
4. 매개변수의 다형성
: 참조형 매개변수는 메서드 호출 시, 자신과 같은 타입 또는 자손타입의 인스턴스를 넘겨줄 수 있다.
class Product {
int price; // 제품가격
int bonusPoint; // 제품 구매 시 제공하는 보너스점수
public Product(int price) {
this.price = price;
bonusPoint = (int)(price/10.0); // 보너스점수는 제품가격의 10%
}
}
class Tv extends Product {
public Tv() { // 조상클래스의 생성자 Product(int price) 호출
super(100); // -> Tv의 가격을 100만원으로 한다.
}
// Objct클래스의 toString()을 오버라이딩한다.
public String toString() { return "Tv"; }
}
class Computer extends Product {
public Computer() { super(200); }
public String toString() { return "Computer"; }
}
class Buyer { // 물건 사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스점수
// Tv, Computer 매개변수 메서드를 따로 만들지 않고 (오버로딩하지 않고) Product 하나로 가능
void buy(Product p) {
if(money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price; // 가진 돈에서 구입한 제품의 가격을 뺀다.
bonusPoint += p.bonusPoint; // 제품의 보너스 점수를 추가한다.
System.out.println(p + "을/를 구입하셨습니다.");
// System.out.println(p.toString() + "을/를 구입하셨습니다.");
// 위와 동일 (p = p.toString())
}
}
public class Poly {
public static void main(String[] args) {
Buyer b = new Buyer();
// Product p = new Tv(); // 클래스 형변환
// b.buy(p); // 이 두 줄을 아래 한 줄로 간단히 -> b.buy(new Tv());
b.buy(new Tv()); // buy(Product p)
b.buy(new Computer()); // buy(Product p)
System.out.println("현재 남은 돈은 " + b.money + "만원입니다.");
System.out.println("현재 보너스 점수는 " + b.bonusPoint + "점입니다.");
}
}
이쯤에서 알아보는 다형성의 장점
- 다형적 매개변수
- 하나의 배열로 여러 종류 객체 다루기
# 종합 예시
class Product {
int price; // 제품가격
int bonusPoint; // 제품 구매 시 제공하는 보너스점수
Product(int price) {
this.price = price;
bonusPoint = (int)(price/10.0); // 보너스점수는 제품가격의 10%
}
Product() { } // 기본 생성자
}
class Tv extends Product {
public Tv() { super(100); }
public String toString() { return "Tv"; }
}
class Computer extends Product {
public Computer() { super(200); }
public String toString() { return "Computer"; }
}
class Audio extends Product {
public Audio() { super(50); }
public String toString() { return "Audio"; }
}
class Buyer { // 물건 사는 사람
int money = 1000; // 소유금액
int bonusPoint = 0; // 보너스점수
Product[] cart = new Product[10]; // 구입한 제품을 저장하기 위한 배열
int i = 0; // Product배열에 사용될 카운터
void buy(Product p) {
if(money < p.price) {
System.out.println("잔액이 부족하여 물건을 살 수 없습니다.");
return;
}
money -= p.price; // 가진 돈에서 구입한 제품의 가격을 뺀다.
bonusPoint += p.bonusPoint; // 제품의 보너스 점수를 추가한다.
cart[i++] = p; // 제품을 Product[] cart에 저장한다.
System.out.println(p + "을/를 구입하셨습니다.");
}
void summary() { // 구매한 물품에 대한 정보를 요약해서 보여준다.
int sum = 0; // 구입한 물품의 가격 합계
String itemList = ""; // 구입한 물품 목록
// 반복문을 이용해서 구입한 물품의 총 가격과 목록을 만든다.
for(int i=0; i<cart.length; i++) {
if(cart[i]==null) break;
sum += cart[i].price;
itemList += cart[i].toString() + ", ";
}
System.out.println("구입하신 물품의 총 금액은 " + sum + "만원입니다.");
System.out.println("구입하신 제품은 " + itemList + "입니다.");
}
}
public class Poly_Ex {
public static void main(String[] args) {
Buyer b = new Buyer();
b.buy(new Tv());
b.buy(new Computer());
b.buy(new Audio());
b.summary();
}
}
* 클래스 형변환
- 상속/구현객체에 있는 클래스(객체)에서 부모타입의 참조변수로 자식객체를 참조할 수 있다.
* 클래스 형변환과 매개변수 다형성 의 차이점 ?
클래스 형변환은 일어나는 현상,
매개변수 다형성은 클래스 형변환이 가능하기 때문에 획득되는 이점이라고 할 수 있다.
* 메소드 재정의
- 부모로부터 물려받은 기능을 자신의 클래스에 맞게 재정의
- 추상화된 기능을 구현하기 -> 사용방법이 동일한 구현클래스의 제작이 가능
* 참고 : 유튜브 [자바의 정석 기초]
< 해당 글은 velog에서 이전하며 옮겨온 글로, 가독성이 좋지 않을 수 있는 점 양해 부탁드립니다. >
🔗 velog 버전 보기 : https://velog.io/@ryuneng2/Java-다형성-Polymorphism
'BackEnd > Java' 카테고리의 다른 글
[Java] StringBuilder, StringBuffer 사용 목적 및 차이점 (0) | 2025.01.15 |
---|---|
[Java] 추상화 - 추상 클래스(Abstract Class), 인터페이스(Interface) 정리 (0) | 2025.01.15 |
[Java] 접근 제어자(access modifier) (Feat. 캡슐화) (0) | 2025.01.15 |
[Java] 오버로딩(Overloading), 생성자(Constructor) (0) | 2025.01.15 |
[Java] static, instance 변수/메서드 정리 (0) | 2025.01.15 |