본문 바로가기

아옳옳의 코딩공부/아옳옳 자바코딩공부

2021-02-23 자바공부 (상속3 이해 , 상속의 사용목적)

반응형

이렇게 어려운 상속의 이야기들을 코드를 보면서 이해를 쉽게 해보자~

 

만들려구 하는프로그램은 일단 타이어라는 클래스르 만들고 최대사용 가능량과 누적 사용량을 계산하여 

누적사용량이 최대사용량을 넘어가면 자동차가 멈추고 타이어를 교체해주는 프로그램을 작성하였다 

코드속에도 주석으로 설명이 써져 있으니 참고하자~ 

 

부모클래스 

package methodoverride;

//부모 클래스 Tire 
public class Tire {
	// 타이어의 기본 속성 등을 담아서 자식클래스에 넘겨 준다
	// 타이어의 최대 사용가능횟수
	int maxRotation;
	// 타이어의 누적 사용량
	// 타이어의 최대 사용가능횟수와 비교하여 타이어 사용횟수가 넘으면 교체를 해준다는걸 보여줄예정
	int accumulationRotate = 0;
	// 타이어의 위치를 받는 변수 (앞 뒤 좌우 라고 생각해 )
	String location;

	// 타이어의 생성자
	public Tire(int maxRotation, String location) {
		this.maxRotation = maxRotation;
		this.location = location;
	}

	// 이번에 배운 오버라이딩을 사용하기 위하여 자식의 메소드와 같은 메소드를 만들어줬다
	// 실제로 사용될 메소드는 자식클래스의 메소드 이므로 사실 내용이 없어도 무관하지만 이해를 돕기위해 만듬
	boolean roll() {
		accumulationRotate++;
		if (accumulationRotate < maxRotation) {
			System.out.println(location + "Tire 수명 : " + (maxRotation - accumulationRotate));
			return true;
		} else {
			System.out.println("****" + location + "Tire 펑크 *****");
		}
		return false;
	}

}

자식클래스 (여기서는 길어기지때문에 코드 한개만 참조 똑같은 hankooktire 클래스 또 있다 ) 

package methodoverride;

//타이어의자식 클래스 금호 타이어클래스 
public class kumhoTire extends Tire {
	// 생성자로 타이어의 위치와 사용가능횟수를 받아온다
	public kumhoTire(int maxRotation, String locaion) {
		// 실제로 타이어의 속성을 상속 받았기 때문에 여기서는 따로 변수 없이 사용
		// super로 부모클래스로 보내주어 인스턴스(객체화) 시켜주었다
		super(maxRotation, locaion);
	}

	// 오버라이딩 상속에서 배운상황을 사용해보자
	@Override
	boolean roll() {
		// 실행되면 상속받은 부모클래스의 누적 사용량 1씩 증가
		accumulationRotate++;
		// 누적 사용량보다 사용가능횟수가 클경우if문 활성화
		if (accumulationRotate < maxRotation) {
			// 아직 사용이 가능한 상태이므로 간단한 상태 출력과 true값 리턴해줌
			System.out.println(location + "Tire 수명 : " + (maxRotation - accumulationRotate));
			return true;
			// 하지만 만약 누적 사용량이 사용가능횟수보다 크거나 같을 경우에 타이어의 
            //문제가 생긴걸 보내준다
		} else {
			System.out.println("****" + location + "Tire 펑크 *****");
		}
		// 리턴값을 false로 보내줌
		return false;
	}
}

자동차 클래스

package methodoverride;
// 자동차 클래스 
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() {
		System.out.println("[자동차가 달립니다.]");
		//자동차가 동작하면서 if 문을 하나씩 검사할것이다.
		//부모클래스(Tire)에 있는 roll 실행 타이어객체 각각에게 물어보고 실행 할것인데 
		// roll에서 누적값 상승 , 누적값과 사용가능값을 계산하여 ture false로 리턴을 해주기 때문에 
		// true이면 넘어가고 false일때 실행
		if (frontLeftTire.roll() == false) {
			//아래 stop() 메소드 실행과 호출했던 메인클래스 problemLocation여기로 리턴값을 보내준다 
			stop();
			return 1;
		} else if (frontRightTire.roll() == false) {
			stop();
			return 2;
		} else if (backLeftTire.roll() == false) {
			stop();
			return 3;
		} else if (backRightTire.roll() == false) {
			stop();
			return 4;
		}
		//하지만 아무 조건에도 걸리지 않았을 경우에 리턴값 0을 보내준다 
		return 0;
	}
	
	void stop() {
		System.out.println("[자동차가 멈춥니다]");
	}
}

메인클래스

package methodoverride;
//메인 클래스 
public class Car_Ex {

	public static void main(String[] args) {
		//자동차 객체화 시켜줌 
		Car car = new Car();

		for (int i = 1; i <= 5; i++) {
			//car 클래스의 run 실행 그곳에서 실행한것이 problemLocation여기 변수로 들어간다 
			int problemLocation = car.run();
			// problemLocation여기서 받은 값이 뭐인지에 따라서 실행 하겠다 
			// 여기서 받은 리턴값에 따라서 case 문이 실행 되겠지만 car 클래스에서 
            //리턴값을 0을 넘겨주면 
			// 아무 문제 없다는 뜻이므로 아무것도 실행 되지 않고 for문으로 돌아감 
			switch (problemLocation) {
			case 1: 
				//만약 누적량이 사용가능횟수 이상이라면 타이어를 교체해준다 
				System.out.println("앞 왼쪽 Hankook Tire로 교체");
				//타이어를 바꿔주면서 자식클래스 한국타이어를 부모 tire클래스로 넘겨 주면서
                //업캐시팅 
				//이렇게 되면 문장이 실행 되며 roll 을 만나는 순간 부모클래스 roll이 아닌 
				//자식 클래스의 오버라이딩 된 roll 메소드를 실행 하게 된다
				car.frontLeftTire = new HankookTire(15, "앞왼쪽 ");
				break;
			case 2:
				System.out.println("앞 오른 kumho Tire로 교체");
				car.frontRightTire= new kumhoTire(13, "앞오른 ");
				break;
			case 3:
				System.out.println("뒤 왼쪽 Hankook Tire로 교체");
				car.backLeftTire = new HankookTire(15, "뒤왼쪽 ");
				break;

			case 4:
				System.out.println("뒤 오른쪽 kumho Tire로 교체");
				car.backRightTire = new HankookTire(13, "뒤오른쪽 ");
				break;
			}
			System.out.println("-------------------------------");
		}

	}

}

 

결과값

클래스들이 많아지면서 헷갈리는건 당연하다 

상위 부모클래스부터 하나씩 보면 대충 어떤 흐름인지 이해는 될거다 ~! 

첨부터 잘하는사람은 없으니까.... ㅜㅠ

 

그래도 어렵다면 다음 코드를 살펴보자 다음코드는 조금더 쉽게 만들어본 클래스이다 .

이해를 돕기위하여 간략하게 만들었ㄷㅏ

 

package methodoverride2;
//-----------------------------------탈것 클래스 
public class Vehicle {

	public void run() {
		System.out.println("차량이 달립니다");
	}
}



package methodoverride2;
//-----------------------------------택시 클래스 e오타... ㄷㄷ 교체하기 귀찮.. ㅋ
public class Texi extends Vehicle {

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


package methodoverride2;
//-----------------------------------버스 클래스
public class Bus extends Vehicle {

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



package methodoverride2;
//----------------------------------드라이버 클래스
public class Driver {

	void drive(Vehicle vehicle) {
		vehicle.run();
	}
}


package methodoverride2;

//----------------------------------메인 클래스
public class Driver_Ex {

	public static void main(String[] args) {

		Driver driver = new Driver();

		// 한개한개 따로 따로 만들어 줬다 지금은 두개이니까 간단한데 나중가면 많아짐 이런식으로 일일이 안만들고
		// 한개씩 다 실행 해준것이다
		Bus bus = new Bus();
		Texi texi = new Texi();

		//driver.drive(texi);
		//driver.drive(bus);

		// 이렇게 하나의 vehicle 안에 버스랑 택시 둘다 담아 주었다
		Vehicle vehicle = new Bus();
		driver.drive(vehicle);

		vehicle = new Texi();
		driver.drive(vehicle);
	}

}


결과값

 

위에보다 기능적인 부분들은 다빼고 상속의 개념 오버라이딩의 개념만 이해하기 쉽게 만들어 보았다 

이거 보면서 이해 ~!!!

 

사실 클래스를 두개만 사용해서 복잡한대 굳이 오버라이딩을 사용해야해? 라는 생각이 들지만... 나중에 고수가 되면 

한두개 클래스가 아닌 엄청나게 많은 클래스들을 사용해야 해서 이렇게 사용하는게 효율적이다!

 

 자 이렇게 복잡한대 .. .상속은 왜 사용 하는 것일까? 

 


상속의 사용이유!!

상속을 통해 연관된 일련의 클래스에 대한 공통적인 규약을 정의할 수 있다!! 

 

위에서 Vehicle 클래스는 인스턴스화 되지 않는다 다만 다른 자식클래스의 상위클래스로만 의미를 지닌다 .

버스클래스와 택시클래스는 Vehicle클래스를 상속받았기 때문에 하위클래스 인스턴스가 가능하다 

 

 

상속을 허용하지 않을때 

클래스나 메소드 앞에 final 을 붙여서 사용하자 

 

사실 나도 배우는 입장이라 책에서 이렇게 말하지만 나중에 고수가 되면 

이 상속이 얼마나 중요한지 알겠지... 그때 까지 쉬지말고 열심히 열공!! 아옳옳ㅇ롷

 

반응형