본문 바로가기
Work & Study/JAVA (& 혼공자Java)

자바(Java) - 필드의 다형성

by a.k.a DUKI 2020. 11. 5.
728x90
반응형

다형성 <= 재정의 + 타입 변환. 앞서 배운 것을 모두 사용한다.

 

필드의 다형성

필드 타입을 부모 타입으로 선언할 경우 다양한 자식 객체가 저장될 수 있기 때문에 필드 사용 결과가 달라 질 수 있다.

 

혼공자 유툽 참고

예시1) 필드의 다형성

Car 클래스로 부터 Car 객체를 생성하여 4개의 Tire필드에 각각 하나씩 Tire 객체가 들어감.

class Car{
	//필드
    Tire frontLeftTire = new Tire();
    Tire frontRightTire = new Tire();
    Tire backLeftTire = new Tire();
    Tire backRightTire = new Tire();
    
    //메소드
    void run(){
    	frontLeftTire.roll();
        frontRightTire.roll();
        backLeftTire.roll();
        backRightTire.roll();
     }   
}     

앞오른 타이어, 뒤왼 타이어를 교체하게되면 아래처럼 코드 작성

Car myCar = new Car();
myCar.frontRightTire = new HankookTire();
myCar.backLeftTire = new KumhoTire();
myCar.run();

frontRightTire, backLeftTire는 원래 Tire객체가 저장되어야 하지만, Tire의 자식 객체가 저장되어도 된다. 자식 타입은 부모 타입으로 자동 타입 변환 되기 때문이다. 

HankookTire, KumhoTire는 부모인 Tire 필드와 메소드를 가지고 있어, Tire자식 객체가 저장되어도 문제가 되지 않는다.

 

 

예시2) 필드의 다형성 Car

Tire 클래스

public class Tire {
	// 필드
	public int maxRotation; // 최대 회전수(타이어수명)
	public int accumulateRotation; // 누적 회전수
	public String location; // 타이어 위치

	// 생성자
	public Tire(String location, int maxRotation) {
		this.location = location; // location 초기화
		this.maxRotation = maxRotation; // maxRotation 초기화
	}

	// 메소드
	public boolean roll() {
		++accumulateRotation; // 누적 회전수 1증가
		if (accumulateRotation < maxRotation) { // 정상회전(누적<최대)일 경우 실행
			System.out.println(location + " Tire 수명: " + (maxRotation - accumulateRotation) + "회");
			return true;
		} else { // 펑크(누적=최대)일 경우 실행
			System.out.println("*** " + location + " Tire 펑크 ***");
			return false;
		}
	}
}

Tire를 부품으로 가지는 클래스

public class Car {
	// 필드 - 자동차의 네개의 바퀴
	Tire frontLeftTire = new Tire("앞왼쪽", 6);
	Tire frontRightTire = new Tire("앞오른쪽", 2);
	Tire backLeftTire = new Tire("뒤왼쪽", 3);
	Tire backRightTire = new Tire("뒤오른쪽", 4);

	// 생성자

	// 메소드
	int run() {//모든 타이어를 1회 회전시키기 위해 각 Tire객체의 roll()메소드 호출
				//false를 리턴하는 roll()이 있을 경우 stop() 메소드를 호출하고 해당 타이어 번호 리턴
		System.out.println("[자동차가 달린다.]");
		if(frontLeftTire.roll()==false) {stop(); return 1;}
		if(frontRightTire.roll()==false) {stop(); return 2;}
		if(backLeftTire.roll()==false) {stop(); return 3;}
		if(backRightTire.roll()==false) {stop(); return 4;}
		return 0;
	}
	
	void stop() { //타이어가 펑크 났을때 실행
		System.out.println("[자동차가 멈춘다.]");
	}
}

Tire의 자식 클래스(HankookTire)

public class HankookTire extends Tire {
	// 필드

	// 생성자
	public HankookTire(String location, int maxRotation) {
		super(location, maxRotation);
	}

	// 메소드
	// 다른 내용을 출력하기 위해 재정의한 roll() 메소드
	@Override
	public boolean roll() {
		++accumulateRotation;
		if (accumulateRotation < maxRotation) {
			System.out.println(location + " HankookTire 수명: " + (maxRotation - accumulateRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " HankookTire 펑크 ***");
			return false;
		}
	}
}

Tire의 자식 클래스(KumhoTire)

public class KumhoTire extends Tire {
	// 필드

	// 생성자
	public KumhoTire(String location, int maxRoation) {
		super(location, maxRoation);
	}

	// 메소드
	// 다른 내용을 출력하기 위해 재정의한 roll() 메소드
	@Override
	public boolean roll() {
		++accumulateRotation;
		if (accumulateRotation < maxRotation) {
			System.out.println(location + " KumhoTire 수명: " + (maxRotation - accumulateRotation) + "회");
			return true;
		} else {
			System.out.println("*** " + location + " KumhoTire 펑크 ***");
			return false;
		}
	}
}

실행 클래스 CarEx

public class CarEx {

	public static void main(String[] args) {
		// Car 객체 생성
		Car car = new Car();

		for (int i = 0; i <= 5; i++) { // Car 객체의 run()메소드 5번 반복
			int problemLocation = car.run();

			switch (problemLocation) {
			case 1:	// 앞왼쪽 타이어가 펑크 났을때 HankookTire로 교체
				System.out.println("앞왼쪽 HankookTire로 교체");
				car.frontLeftTire = new HankookTire("앞왼쪽", 15);
				break;
			case 2:	// 앞오른쪽 타이어가 펑크 났을때 KumhoTire로 교체
				System.out.println("앞오른쪽 KumhoTire로 교체");
				car.frontRightTire = new KumhoTire("앞오른쪽", 15);
				break;
			case 3:	// 뒤왼쪽 타이어가 펑크 났을때 HankookTire로 교체
				System.out.println("뒤왼쪽 HankookTire로 교체");
				car.backLeftTire = new HankookTire("뒤왼쪽", 15);
				break;
			case 4: // 뒤오른쪽 타이어가 펑크 났을때 KumhoTire로 교체
				System.out.println("뒤오른쪽 KumhoTire로 교체");
				car.backRightTire = new KumhoTire("뒤오른쪽", 15);
				break;
			}
			System.out.println("-------------------------------------");
		}
	}

}

 

 

 

매개 변수의 다형성

매개 변수를 부모 타입으로 선언하는 효과

  • 메소드 호출시 매개값으로 부모 객체 및 모든 자식 객체를 제공할 수 있다.
  • 자식의 재정의된 메소드가 호출 -> 다형성
//Driver 클래스에 drive()메소드 정의되어있고, Vehicle타입의 매개변수 선언
class Driver{
	void drive(Vehicle vehicle){
    	vehicle.run();
    }
}    
//drive() 메소드 호출
Driver driver = new Driver();
Vehicle vehicle = new Vehicle();
driver.drive(vehicle);

혼공자 유툽 참고

Vehicle vehicle = bus; //자동 타입 변환

 

매개 변수의 다형성은 매개값으로 어떤 자식 객체가 제공되느냐에 따라 메소드의 싱행결과가 다양해질 수 있다는 것이다.

 

예시3) 매개 변수의 다형성 Vehicle

부모 클래스

public class Vehicle {
	public void run() {
		System.out.println("차량이 달린다.");
	}
}

Vehicle을 이용하는 클래스

public class Driver {
	// Driver클래스인데, drive()메소드에서 Vehicle타입의 매개값을 받아서 run()메소드 호출
	public void drive(Vehicle vehicle) {
		vehicle.run();
	}
}

자식 클래스 (Bus)

public class Bus extends Vehicle {
	@Override
	public void run() {
		System.out.println("버스가 달립니다.");
	}
}

자식 클래스 (Taxi)

public class Taxi extends Vehicle {
	@Override
	public void run() {
		System.out.println("택시가 달립니다.");
	}
}

실행 클래스 DriverEx

public class DriverEx {

	public static void main(String[] args) {
		Driver driver = new Driver();

		Bus bus = new Bus();
		Taxi taxi = new Taxi();

		driver.drive(bus); 	// 자동 타입 변환: Vehicle vehicle = bus;
		driver.drive(taxi); // 자동 타입 변환: Vehicle vehicle = taxi;
	}

}

 

 

 

 

 


※용어 정리

  • 클래스 타입 변환: 다른 클래스 타입으로 객체를 대입하는 것

  • 자동 타입 변환: 자식 객체를 부모 타입 변수에 대입할 때에는 자동으로 타입이 변환 된다.

 

본 내용은 #혼자공부하는자바 책을 참고해 공부하려 작성했습니다.

 

728x90
반응형