다형성

Mia Lee·2021년 12월 23일
0

JAVA

목록 보기
77/98
package ex_polymorphism;

public class Ex1 {

	public static void main(String[] args) {

		/*
		 * 다형성(Polymorphism)
		 * 
		 * - 동적 바이딩 : 코드상의 실행할 메서드와 컴파일 후 실행 시점에서 
		 *                 실행되는 메서드가 달라지는 것
		 * - 서브클래스에 오버라이딩 된 메서드가 존재할 경우 업캐스팅 후에도 오버라이딩 된
		 *   메서드가 호출됨
		 *   => 즉, 메서드 호출 시 참조 타입이 누군지는 중요하지 않고 실제 인스턴스가 누군지가 중요!
		 */
		
		System.out.println("===== Truck =====");
		// Truck 인스턴스 생성 및 접근 가능한 메서드 호출
		Truck truck = new Truck();
		
		// Car 클래스로부터 상속받은 메서드
		truck.speedUp();
		truck.speedDown();
		
		// Truck 클래스에서 정의한 메서드
		truck.dump();
		
		System.out.println("===== Taxi =====");
		// Taxi 인스턴스 생성 및 접근 가능한 메서드 호출
		Taxi taxi = new Taxi();
		
		// Car 클래스로부터 상속받은 메서드
		taxi.speedUp();
		taxi.speedDown();
		
		// Taxi 클래스에서 정의한 메서드
		taxi.lift();
		taxi.drop();
		
		System.out.println("===== Truck -> Car 업캐스팅 =====");
		Car car = truck; // 업캐스팅
		// Truck -> Car 업캐스팅 후 접근 가능한 메서드 호출
		car.speedUp(); // 서브클래스에서 오버라이딩된 메서드 호출
		car.speedDown(); // 서브클래스에서 오버라이딩 된 메서드 호출
		// => 업캐스팅 후에는 오버라이딩된 Truck의 메서드 호출!
		
//		car.dump(); // 참조 영역 축소로 상속 멤버 외에 접근 불가
		
		System.out.println("===== Car -> Truck 다운캐스팅 =====");
		// 업캐스팅 된 Car 타입을 다시 Truck 타입으로 다운캐스팅
//		truck = car; // 다운캐스팅 시 명시적 형변환 필요
		truck = (Truck) car; // 다운캐스팅
		
		// Car 클래스로부터 상속받은 메서드
		truck.speedUp();
		truck.speedDown();
		
		// Truck 클래스에서 정의한 메서드
		truck.dump();
		
		System.out.println("===== Taxi -> Car 업캐스팅 =====");
		// Taxi -> Car 업캐스팅 및 접근 가능한 메서드 호출
		car = taxi;
		
		car.speedUp();
		car.speedDown();
		// => 업캐스팅 후에도 오버라이딩된 Taxi의 메서드 호출!
		
		// 참조 영역 축소로 상속 멤버 외에 접근 불가
//		car.lift();
//		car.drop();
		
		System.out.println("===== Car -> Taxi 다운캐스팅 =====");
		// 업캐스팅 된 Car 타입을 다시 Taxi 타입으로 다운캐스팅
		taxi = (Taxi) car;
		
		// Car 클래스로부터 상속받은 메서드
		taxi.speedUp();
		taxi.speedDown();
		
		// Taxi 클래스에서 정의한 메서드
		taxi.lift();
		taxi.drop();
		
	}

}

/*
 * Car 클래스 정의
 * - 메서드 정의 : 파라미터 없음, 리턴값 없음
 *   1) speedUp() => "Car의 속력 증가!" 출력
 *   2) speedDown() => "Car의 속력 감소!" 출력
 *   
 * Truck 클래스 정의 -> Car 클래스 상속
 * - 메서드 정의 : 파라미터 없음, 리턴값 없음
 *   1) speedUp() / speedDown() 메서드 오버라이딩
 *      => "Truck의 속력 증가!" / "Truck의 속력 감소!" 출력
 *   2) dump() => "Truck의 짐 싣기!" 출력
 *   
 * Taxi 클래스 정의 -> Car 클래스 상속
 * - 메서드 정의 : 파라미터 없음, 리턴값 없음
 *   1) speedUp() / speedDown() 메서드 오버라이딩
 *      => "Taxi의 속력 증가!" / "Taxi의 속력 감소!" 출력
 *   2) lift() => "Taxi의 승객 승차!" 출력
 *   3) drop() => "Taxi의 승객 하차!" 출력
 *   
 */
class Car {
	
	public void speedUp() {
		System.out.println("Car의 속력 증가!");
		
	}
	
	public void speedDown() {
		System.out.println("Car의 속력 감소!");
		
	}
	
}

class Truck extends Car {

	@Override
	public void speedUp() {
		System.out.println("Truck의 속력 증가!");
		
	}

	@Override
	public void speedDown() {
		System.out.println("Truck의 속력 감소!");
		
	}
	
	public void dump() {
		System.out.println("Truck의 짐 싣기!");
		
	}
	
}

class Taxi extends Car {

	@Override
	public void speedUp() {
		System.out.println("Taxi의 속력 증가!");
		
	}

	@Override
	public void speedDown() {
		System.out.println("Taxi의 속력 감소!");
		
	}
	
	public void lift() {
		System.out.println("Taxi의 승객 승차!");
		
	}
	
	public void drop() {
		System.out.println("Taxi의 승객 하차!");
		
	}
	
}

















연습

package ex_polymorphism;

public class Test1 {

	public static void main(String[] args) {

		// Circle 인스턴스 생성
		Circle c = new Circle();
		c.rad = 3;
		c.draw();
		
		// Rectangle 인스턴스 생성
		Rectangle r = new Rectangle();
		r.line1 = 10;
		r.line2 = 20;
		r.draw();
		
		// Triangle 인스턴스 생성
		Triangle t = new Triangle();
		t.a = 10;
		t.b = 20;
		t.c = 30;
		t.draw();
		
		System.out.println("============================");
		
		Shape s = c; // 업캐스팅
		s.draw(); // 서브클래스에서 오버라이딩 된 메서드 호출
		
		s = r;
		s.draw();
		
		s = t;
		s.draw();
		
		System.out.println("============================");
		
		shapeDraw(c);
		shapeDraw(r);
		shapeDraw(t);
		
		System.out.println("============================");
		
		Circle c2 = new Circle();
		shapeDraw(c2); // Cricle -> Shape 업캐스팅
		// 메서드 파라미터 전달 시 각 클래스 타입이 아닌
		// 클래스들의 슈퍼클래스 타입의 매개변수로 전달받을 경우
		// 하나의 메서드만으로도 여러 인스턴스 파라미터를 전달받을 수 있음!
		
		Rectangle r2 = new Rectangle();
		shapeDraw(r2);
		
		Triangle t2 = new Triangle();
		shapeDraw(t2);
		
		Shape s2 = new Shape();
		shapeDraw(s2);
		
	} // main() 끝
	
	// Circle, Rectangle, Triangle 타입 인스턴스를 하나의 메서드에서
	// 모두 전달받으려면 업캐스팅 활용하여 파라미터 선언
	// => 즉, 공통된 슈퍼클래스 타입인 Shape 타입의 변수를 메서드의 매개변수로
	//    선언하면 모든 인스턴스를 하나로 전달 가능
	public static void shapeDraw(Shape s) {
		// 업캐스팅 후에도 공통된 메서드인 draw() 호출이 가능
		s.draw();
		
	}
	// 다형성을 이용해 메서드의 파라미터를 구성할 때는 사위 타입을 잡는 것이 좋다!
	// => 다만, 최상위의 Object까지 올라가면 별도의 형변환 절차가 필요해져서 번거룸이 커짐!
	
	// =========================================================
	
//	public static void shapeDraw(Circle x) {
//		x.draw();
//	}
//	
//	public static void shapeDraw(Rectangle x) {
//		x.draw();
//	}
//	
//	public static void shapeDraw(Triangle x) {
//		x.draw();
//	}
	// 메서드 오버로딩을 통해 다른 타입의 파라미터를 전달받을 수는 있음
	// => 코드의 중복이 발생함

	
}

/*
 * 도형(Shape) 클래스 정의
 * - draw() 메서드 정의 : 파라미터 없음, 리턴값 없음
 *   => "도형 그리기!" 출력
 *   
 * 원(Circle) 클래스 정의 - 도형(Shape) 클래스 상속
 * - 멤버변수 : 반지름(rad, 실수)
 * - draw() 메서드 오버라이딩
 *   => "반지름 x을 사용하여 원 그리기!" 출력
 *   
 * 사각형(Rectangle) 클래스 정의 - 도형(Shape) 클래스 상속
 * - 멤버변수 : 두 직선의 길이(line1, line2, 정수형)
 * - draw() 메서드 오버라이딩
 *   => "x, y 직선 두 개 사용하여 사각형 그리기!" 출력
 *   
 * 삼각형(Triangle) 클래스 정의 - 도형(Shape) 클래스 상속
 * - 멤버변수 : 세 꼭지점의 좌표(a, b, c, 정수형)
 * - draw() 메서드 오버라이딩
 *   => "x, y, z 꼭지점 세 개 사용하여 삼각형 그리기!" 출력
 *   
 */

class Shape {
	public void draw() {
		System.out.println("도형 그리기!");
		
	}
}

class Circle extends Shape {
	double rad;

	@Override
	public void draw() {
		System.out.println("반지름 " + rad + "을 사용하여 원 그리기!");
		
	}
	
}

class Rectangle extends Shape {
	int line1, line2;

	@Override
	public void draw() {
		System.out.println(line1 + ", " + line2 + " 직선 두 개 사용하여 사각형 그리기!");
		
	}
	
}

class Triangle extends Shape {
	int a, b, c;

	@Override
	public void draw() {
		System.out.println(a + ", " + b + ", " + c + " 꼭지점 세 개 사용하여 삼각형 그리기!");
		
	}
	
}












0개의 댓글