09009

[Java] 다형성, 오버라이딩 (2) 본문

Back-End/JAVA
[Java] 다형성, 오버라이딩 (2)
09009

다형성을 이용한 인스턴스 생성

public class P6 {
	public static void main(String[] args) {
		BB b = new BB();
		AA a = new BB(); 
//		BB b = new AA(); 에러
		CC c = new CC();
		AA a2 = new CC();
		BB b2 = new CC();
		
		DD d1 = new DD();
		AA aa = new DD();
		
//		BB b3 = new DD(); 에러
		
		AA a4 = new AA();
		AA a5 = new BB();
		AA a6 = new CC();
		AA a7 = new DD();
		
		CC c10 = new CC();
		AA a10 = new CC();
		
		c10.va = 10;
		c10.vb = 20;
		c10.vc = 30;
		
		a10.va = 10;
//		a10.vb = 20; // 에러
	}
}

class AA {
	int va;
}

class BB extends AA {
	int vb;
}

class CC extends BB {
	int vc;
}

class DD extends AA {
	int vd;
}


에러 코드 분석

1)

BB 클래스가 AA 클래스를 상속받은 상태에서 실제 인스턴스인 AA의 멤버 개수보다
참조변수 b가 사용할 수 있는 멤버 개수가 더 많기 때문에 자바에서는 이를 허용하지 않아 에러를 발생시킨다.
 
자손타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은
존재하지 않는 멤버를 사용하려고 할 가능성이 있기 때문에  자바에서 허용하지 않는 것이다.
참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.
 

2)


DD 클래스와 BB 클래스는 모두 AA 클래스를 상속받은 상태이다.
위 소스코드만 확인하였을 때 BB와 DD 클래스는 서로 상속 관계임을 확인할 수 없기 때문에
위와 같이 다형성을 이용한 인스턴스 생성을 할 수 없다.

 

3)

CC 클래스는 BB 클래스를 상속받았고, BB 클래스는 AA 클래스를 상속받았기 때문에
CC 클래스는 BB 클래스와 AA 클래스에 있는 멤버를 사용할 수 있다.

참조변수 a10의 경우, CC의 부모인 AA를 선언하고 자손 CC를 생성하였는데 이와 같은 경우,
부모가 가지고 있는 메서드와 멤버변수만 사용 가능하다. 
 
부모 타입의 참조변수로는 자손 인스턴스 중에서 부모 클래스의 멤버들(상속받은 멤버 포함)만 사용할 수 있는데
AA 클래스는 vb 변수를 가지고 있지 않기 때문에 에러가 발생한 것이다.
 
자손타입의 참조변수로 조상타입의 인스턴스를 참조하는 것은
존재하지 않는 멤버를 사용하려고 할 가능성이 있기 때문에 자바에서 이를  허용하지 않는다.
참조변수가 사용할 수 있는 멤버의 개수는 인스턴스의 멤버 개수보다 같거나 적어야 한다.
 



 
오버라이딩 예제

public class P7 {
	public static void main(String[] args) {
		SCV s1 = new SCV();
		Marine m1 = new Marine();
		Tank t1 = new Tank();
	}
}

class SCV {
	int hp = 50;
	int speed = 3;
	int ap = 1;
}

class Marine {
	int hp = 100;
	int speed = 5;
	int ap = 5;
}

class Tank {
	int hp = 200;
	int speed = 7;
	int ap = 20;
}

모든 유닛은 움직이는 기능을 가지고 있다.
각각의 유닛은 움직이는 속도가 다르다는 것을 아래와 같이 정의한다.

 

위의 소스코드 대신 다형성을 이용하여 아래와 같이 코드를 변경하는 것이 바람직하다.

public class P7 {
	public static void main(String[] args) {
		Unit[] arr = new Unit[12];
		
		// 다형성으로 묶는다.
		arr[0] = new Marine();
		arr[1] = new Tank();
		arr[2] = new SCV();	
		arr[3] = new Tank();
		arr[4] = new Tank();
		arr[5] = new SCV();
		arr[6] = new Tank();
		arr[7] = new Tank();
		arr[8] = new Marine();
		arr[9] = new Marine();
		arr[10] = new Marine();
		arr[11] = new Marine();
		
		// 이동
		for(Unit u : arr) {
			u.move();
		}
		
		
	}
}

class Unit { // unit은 실체가 없기 때문에 값을 초기화할 수 없다.
	int hp;
	int speed;
	int ap;
	
	void move() {
		System.out.println("유닛이 " + speed + "로 이동합니다.");
	}
	
	void stop() {
		System.out.println("유닛이 멈춥니다.");
	}
	
	void attack() {
		System.out.println("유닛이 " + ap + "로 공격합니다.");
	}
}

class SCV extends Unit {
	SCV() {
		this.ap = 1;
		this.hp = 1;
		this.speed = 1;
	}
}

class Marine extends Unit {
	Marine() {
		this.ap = 2;
		this.hp = 2;
		this.speed = 2;
	}
}

class Tank extends Unit {
	Tank() {
		this.ap = 3;
		this.hp = 3;
		this.speed = 3;
	}
}

 

 

/

5/7