[JAVA]/09. 다형성

09. 다형성코드예제 ver.2( 부모클래스를 추상클래스로!)

76beny 2022. 4. 15. 21:08

■ 부모클래스( ver1 과 다르게 추상클래스로!)

- abstract : 추상클래스로 만드는 키워드

[abstract의 특징]

1.생성되지 않는다.
2.abstract 메소드를 가질 수 있다.
3. 일반 메소드나 멤버변수 선언이 자유롭다.
사용방법: 상속이나  Type으로 활용된다.

package com.kh.ex03.poly_abstract;

public abstract class Car { // 부모 클래스,abstract 추상클래스로 만들어 버림
	protected int cc = 0; // cc : 배기량

	public Car(int cc) {
		this.cc = cc;
	}
	
	public void oilling() {
		System.out.println("주유중 입니다.");
	}
	
	public void move() {
		System.out.println("부릉부릉");
	}
	
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		sb.append("Name : " + this.getClass().getSimpleName());
		sb.append(", cc : " + cc);
		return sb.toString();
	}
}

■ 부모클래스에 상속된 추상클래스 추가로 만들기

-현대i카 라는 추상클래스를 만들어서 국산 자동차를 그룹화해보는것!

[일반메소드와 추상메소드의 차이]

추상메소드 : 몸통을 가지지 않는다! 그리고 상속받은 클래스에서 강제로 생성한다.

일반메소드 : 공통적인 기능을 가질때 사용.

package com.kh.ex03.poly_abstract;

public abstract class HyundaiCar extends Car {//HyundaiCar(브랜드)를 추상클래스로 하나 만들기
	//abstract class의 특징
	//1.생성되지 않는다.
	//2.abstract 메소드를 가질 수 있다.
	//3. 일반 메소드나 멤버변수 선언이 자유롭다.
	//사용방법: 상속이나  Type으로 활용된다.
	
	public HyundaiCar(int cc) {
		super(cc);

	}
	
	//추상메소드 : 몸통을 가지지 않는다! 그리고 상속받은 클래스에서 강제로 생성한다.
	//현대종류 차들이 공통적으로 각자 가지고 있었던 nickName을 추상메소드로 만들어버림
	abstract public void nickName();//앞으로 nickName이렇게만 쓰라고 박아버리는것

	//일반메소드 : 공통적인 기능을 가질때 사용.
	//현대차는 블루핸즈에서 수리받을수 있다(가정)해서 service로 메소드 추가로 생성함.
	public void service() { 
		System.out.println("블루핸드로 출발합니다.");
	}

//	public static void main(String[] args) { // 생성 불가능함. why?
//		HyundaiCar Car = new HyundaiCar(13) {//추상클래스는 생성되지 않기 떄문이다!
//	}


}

■ 자손클래스 -1 ( 국산차)

- 부모클래스에 상속된 현대i카 라는 추상클래스에 (국산차)자손클래스들을 상속한다.(BMWM5,테슬라제외)

//<Avante>

package com.kh.ex03.poly_abstract;

public class Avante extends HyundaiCar {//클래스 이름을 Car->HyundaiCar로 변경한다 
	//why? HyundaiCar.java에서 상속했기 때문에 바꾸기 (Car>HyundaiCar>Avante)개념

	public Avante() {
		super(1600); // 아반떼는 1600cc 이다.
	}
	
	@Override
	public void oilling() {
		System.out.println("휘발유를 주유중입니다.");
	}

	
	//AvantenickName을 nickName으로 변경한다
	//why? Avante보다 상위클래스인 HyundaiCar에서 각 차들의 각각 설정된 닉네임을
	//abstract public void nickName();로 추상메소드로 만들었기 때문에!
	@Override
	public void nickName() {
		System.out.println("아방이");
	}

}
//<Grandure>

package com.kh.ex03.poly_abstract;

public class Grandure extends HyundaiCar {//클래스 이름을 Car->HyundaiCar로 변경한다 
	//why? HyundaiCar.java에서 상속했기 때문에 바꾸기 (Car>HyundaiCar>Grandure)개념

	public Grandure() {
		super(3000); // 3000cc
	}
	
	@Override
	public void oilling() {
		System.out.println("휘발유를 주유중입니다.");
	}
	
	@Override
	public void move() {
		System.out.println("(조용한)부르르르르릉");
	}
	
	//GrandurenickName을 nickName으로 변경한다
	//why? Grandure보다 상위클래스인 HyundaiCar에서 각 차들의 각각 설정된 닉네임을
	//abstract public void nickName();로 추상메소드로 만들었기 때문에!
	
	@Override
	public void nickName() {
		System.out.println("각그랜저");
	}
}
package com.kh.ex03.poly_abstract;

public class Sonata extends HyundaiCar{//클래스 이름을 Car->HyundaiCar로 변경한다 
	//why? HyundaiCar.java에서 상속했기 때문에 바꾸기 (Car>HyundaiCar>Sonata)개념

	public Sonata() {
		super(2000); // 2000 CC
	}
	
	@Override
	public void oilling() {
		System.out.println("휘발유를 주유중입니다.");
	}
	
	@Override
	public void move() {
		System.out.println("부르르르르릉");
	}
	
	
	//SonatanickName을 nickName으로 변경한다
	//why? Sonata보다 상위클래스인 HyundaiCar에서 각 차들의 각각 설정된 닉네임을
	//abstract public void nickName();로 추상메소드로 만들었기 때문에!
	@Override
	public void nickName() {
		System.out.println("소나 타는 차"); // 실제 이름의 유례, 고 정주영 회장님의...
	}
}

■ 자손클래스_2 ( 테슬라, BMWM5 : 해외차라서 현대i카 클래스에 상속시키지 않고 부모클래스에만 상속시킴)

//<BMWM5>

package com.kh.ex03.poly_abstract;

public class BMWM5 extends Car{

	public BMWM5() {
		super(4395); // cc가 커지면 배기량 올라감 = 힘, 토크, 마력
	}
	
	@Override
	public void oilling() {
		System.out.println("고급 휘발유를 주유중입니다.");
		System.out.println("기름을 땅바닥에 뿌립니다.");
	}
	
	@Override
	public void move() {
		System.out.println("부와와와와와왕아아아앙앙(시끄럽게)");
	}

	void doc3sa() { // 독삼사 = BMW, 벤츠, 아우디
		System.out.println("나는 독일에서 온 자동차야.");
	}
}
//<TeslaModel3>

package com.kh.ex03.poly_abstract;

public class TeslaModel3 extends Car {
	//다른 규격의 자동차모델 자식클래스를 생성했을경우! => 어떻게하는지 ex04에서 보자!

	// 전기차인데... CC?
	public TeslaModel3() {// 해외 전기차이기때문에 현대차랑 규격(연비단위) 틀림(가정한다)
		super(175); // kw/h 단위인데... cc?
	}

	@Override//생성
	public void oilling() { // 호환 안되는듯?// 전기차는 오일링이 아니니까!(가정함)
		System.out.println("충전중인데... 오일링?");
	}
	
	@Override//생성
	public void move() {
		System.out.println("(조용히) 위이이이이이잉");
	}
}

■ Run

package com.kh.ex03.poly_abstract;

public class _Run {

	public static void main(String[] args) {
		Car[] carArray = new Car[4];// 4로 변경
		//System.out.println(Arrays.toString(carArray));

		//carArray[0] = new Car(1000); // 추상클래스는 생성되지 않음!
		carArray[0] = new Avante();
		carArray[1] = new Sonata();
		carArray[2] = new Grandure();
		carArray[3] = new BMWM5();

		for (int i = 0; i < carArray.length; i++) {
			//((Avante)carArray[i]).oilling(); // java.lang.ClassCastException(오류뜸)
			// why? 캐스팅 잘못해서(형변환 잘못해서?) => 형변환 함부로 하면 안되고 instanceof로 타입 체크하면서 변환해야함!
			printCar(carArray[i]);
		}
	}

	private static void printCar(Car car) { // 인자가 다형성 속성을 사용중
		System.out.println(car.toString());

		car.move(); // 동적 바인딩 : 실행 전에 호출될 메소드를 정하지 않고,
								   //실행 후 실시간(동적)으로 메소드를 호출하는 방법
		car.oilling();

		//ex02패키지의 Run 에서 instanceof뒤에 현대 차종류 별로 각각 되있던걸 새로 생성한 상위추상클래스인HyundaiCar 로 변경해줌.
		if (car instanceof HyundaiCar) {
			((HyundaiCar) car).nickName(); // 추상클래스로 Type Casting이 가능하다!즉, HyundaiCar를 타입으로 씀!
			((HyundaiCar) car).service();// 현대차는 모두 블루핸즈로 출발합니다가 뜸(HyundaiCar추상클래스에 있던 메소드)
		}
		if (car instanceof BMWM5) {
			((BMWM5) car).doc3sa();
		}
		System.out.println("--------------------------------------");
	}
}

//동적바인딩 : 실행전에 호출될 메소드를 정하지 않고, 실시간(동적)으로 메소드를 호출하는 방법.