다형성 : 하나의 타입에 여러 객체를 대입함으로써 다양한 기능을 이용할 수 있도록 함
- 부모 타입에 모든 자식 객체를 대입 가능 > 객체의 부품화가 가능함
타입 변환 : 데이터 타입을 다른 데이터 타입으로 변환하는 행위 (기본 타입 변환 설명 글)
- 클래스 타입의 변환은 상속 관계에 있는 클래스 사이에서 발생하며 자식 타입은 부모 타입으로 자동 타입 변환이 가능
1. 자동 타입 변환 (promotion) : 프로그램 실행 도중 자동적으로 타입 변환이 일어나는 것
부모클래스 변수 = 자식클래스타입;
- 자식은 부모의 특징과 기능을 상속받기 때문에 부모와 동일하게 취급 가능
class Animal { ... }
class Cat { ... }
Cat cat = new Cat(); // Cat 객체 참조
Animal animal1 = cat; // Cat 객체 참조
Animal animal2 = new Cat();
cat == animal1 // true
- 자동 타입 변환한 두 변수는 동일한 객체를 참조
- 바로 위의 부모가 아니더라도 상속 계층에서 상위 타입이라면 자동 타입 변환 가능
public class Parent {
public void method1() {
System.out.println("Parent-method1()");
}
public void method2() {
System.out.println("Parent-method2()");
}
}
public class Child extends Parent {
@Override
public void method2() {
System.out.println("Child-method2()");
}
public void method3() {
System.out.println("Child-method3()");
}
}
public class Example {
public static void main(String[] args) {
Child child = new Child();
Parent parent = child;
parent.method1(); // Parent-method1()
parent.method2(); // Child-method2()
// parent.method3(); 호출 불가능
}
}
- 부모 타입으로 자동 타입 변환된 후에는 부모 클래스에 선언된 필드와 메소드만 접근 가능
- 변수는 자식 객체를 참조하지만 접근 가능한 멤버는 부모 클래스 멤버만 가능
- 메소드가 자식 클래스에서 오버라이딩 되었다면 자식 클래스의 메소드가 대신 호출됨
2. 필드의 다형성
다형성 : 동일한 타입을 사용하지만 다양한 결과가 나오는 성질
- 필드의 값을 다양화함으로써 실행 결과가 다르게 나오도록 구현
- 필드 타입은 변함 없지만, 실행 도중 어떤 객체를 필드로 저장하느냐에 따라 실행 결과가 달라질 수 있음
- 프로그램은 수많은 객체들의 연결이고 각 객체들은 자신의 역할을 수행하는데, 이러한 객체는 언제든지 다른 객체로 교체될 수 있어야 함
- 상속, 오버라이딩, 타입 변환을 적절히 사용하여 다형성을 구현
3. 하나의 배열로 객체 관리
- 동일한 타입의 값들은 배열로 관리하는 것이 유리
- 부모 타입의 배열에 자식 객체를 대입하면 자동 타입 변환이 발생하므로 문제 없음
- 상속 관계에 있는 객체들은 배열로 관리하면 제어문에서 혜택을 봄
public class Tire {
// 필드
public int maxRotation; // 최대 회전수 (타이어 수명)
public int accumulatedRotation; // 누적 회전수
public String location; // 타이어의 위치
// 생성자
public Tire(String location, int maxRotation){
this.location = location;
this.maxRotation = maxRotation;
}
// 메소드
public boolean roll() {
++accumulatedRotation; // 누적 회전수 1 증가
if (accumulatedRotation<maxRotation) {
System.out.println(location + "Tire 남은 회전수 : " + (maxRotation-accumulatedRotation) + "회");
return true;
} else {
System.out.println("*** " + location + " Tire 펑크 ***");
return false;
}
}
}
public class Car {
// 필드
Tire[] tires = {new Tire("앞왼쪽", 6), new Tire("앞오른쪽", 2), new Tire("뒤왼쪽", 3), new Tire("뒤오른쪽", 4)};
// 생성자
// 메소드
int[] run() {
System.out.println("자동차 주행");
int[] result = {0, 0, 0, 0}; // 펑크난 타이어 번호를 저장
for (int i = 0; i < tires.length; i++) {
if (tires[i].roll() == false) {
stop();
result[i] = i+1;
}
}
return result;
}
void stop() {
System.out.println("자동차 멈춤");
}
}
public class HankookTire extends Tire {
// 필드
// 생성자
public HankookTire(String location, int maxRotation) {
super(location, maxRotation);
}
// 메소드
@Override
public boolean roll() {
++accumulatedRotation; // 누적 회전수 1 증가
if (accumulatedRotation < maxRotation) {
System.out.println(location + "HankookTire 남은 회전수 : " + (maxRotation-accumulatedRotation) + "회");
return true;
} else {
System.out.println("*** " + location + " HankookTire 펑크 ***");
return false;
}
}
}
public class Example {
public static void main(String[] args) {
Car car = new Car();
for (int i = 1; i <= 5; i++) {
int[] problemLocations = car.run();
// 펑크난 타이어가 존재하면 해당 타이어를 한국타이어로 교체
for (int problemLocation : problemLocations) {
if (problemLocation != 0) {
System.out.println(car.tires[problemLocation - 1].location + " HankookTire로 교체");
car.tires[problemLocation - 1] = new HankookTire(car.tires[problemLocation - 1].location, 15);
}
}
System.out.println("-----------------------------------");
}
}
}
- 교제에는 앞선 타이어부터 문제가 생기면 남은 타이어가 회전하지 않는 문제가 존재해서 앞선 타이어에서 문제가 발생하더라도 남은 타이어 모두 1회씩 회전하도록 예제를 변경함
4. 매개 변수의 다형성
- 자동 타입 변혼은 필드의 값을 대입할 때에도 발생하지만, 주로 메소드를 호출할 때 많이 발생
- 메소드를 호출할 때, 매개값을 다양화하기 위해 매개 변수에 자식 타입 객체를 지정할 수도 있음
- 매개 변수이 타입이 클래스일 경우, 해당 클래스의 객체뿐만 아니라 자식 객체까지도 매개값으로 사용 가능
- 자식 객체가 부모의 메소드를 오버라이딩했다면 메소드 내부에서 오버라이딩된 메소드를 호출함으로써 메소드의 실행 결과가 다양해짐
5. 강제 타입 변환 (Casting) : 자식 타입이 부모 타입으로 자동 변환한 후, 다시 자식 타입으로 변환하는 것
자식클래스 변수 = (자식클래스) 부모타입으로변환된자식타입변수;
- 부모 타입으로 자동 타입 변환된 자식 타입 객체는 부모 타입의 필드와 메소드만 사용 가능하기 때문에, 자식 타입의 필드와 메소드를 꼭 사용해야한다면 강제 타입 변환을 사용해 다시 자식 타입으로 변환해야 함
6. 객체 타입 확인 (instanceof)
- 어떤 객체가 어떤 클래스의 인스턴스인지 확인할 수 있는 연산자 / 매개값의 타입을 조사할 때 주로 사용
boolean result = 객체 instanceof 타입
- 좌항엔 객체, 우항엔 타입이 오며, 좌항이 우항의 타입으로 객체가 생성되었다면 true
- 강제 타입 변환을 하기 전 instanceof 연산자로 변환시킬 타입의 객체인지 조사하는 과정이 필요
'언어 > Java' 카테고리의 다른 글
| 중첩 클래스와 인터페이스 (0) | 2023.08.29 |
|---|---|
| 인터페이스 (1) | 2023.08.27 |
| 메소드 재정의 (오버라이딩) (0) | 2023.08.24 |
| 상속 (0) | 2023.08.24 |
| 어노테이션 (0) | 2023.08.24 |