객체 형변환과 객체 배열

9mond·2023년 7월 11일
0
post-thumbnail
post-custom-banner

1. 객체 형변환이란?

  • java 기본 유형의 데이터들처럼 객체 참조변수의 경우에도 형변환(Casting)이 이루어진다.
  • 서로 다른 클래스 유형으로부터 나온 객체 참조변수들 간의 대입에는 일정한 규칙이 있다.
	Parent parent = new Child();
  • 위의 대입연산에서 왼쪽항(Parent)과 오른쪽항(Child)의 객체 유형이 서로 다른 경우, 두 유형이 서로 상속 관계에 있고 왼쪽 객체(Parent)가 오른쪽 객체(Child)의 상위 클래스인 경우에만 암묵적인 형변환이 일어난다.
  • 하위 클래스에서 상위 클래스 유형으로 할당하는 것은 가능하나 그 경우에는 명시적 형변환을 해야한다.

2. 객체 간의 암묵적 형변환

	A a1 = new B();
	A a2 = new X();
	----------------
	A a3 = new C();
	A a4 = new Y();
	-----------------
	B b1 = new C();
	X x1 = new Y();
	------------------
	C c = new C();
	B b2 = c;
	------------------
	Y y = new Y();
	X x2 = y;

3. 암묵적 형변환과 메서드 오버라이드

  • 암묵적 형변환은 부모를 상속받은 자식 객체의 기능을 부모에게 물려받은 기능만 사용하도록 제한한다.
  • 그러므로 암묵적 형변환이 발생하면 오버라이드 된 기능만 사용 가능하고, 추가적으로 구현한 기능은 사용할 수 없다.

    주의할 점은 기능의 제한이지 기능의 변경은 아니라는 것이다.

  • 상속관계의 객체를 부모 형태로 변환하면 클래스의 종류를 구분하지 않고, 일관된 기능을 호출할 수 있다.
  • 객체가 상위 클래스 형태로 형변환 되더라도 Override된 자신의 기능은 잃지 않는다.
	Unit u1 = army;
	Unit u2 = navy;
	Unit u3 = airforce;

	u1.attack();
	u2.attack();
	u3.attack();
  • 하지만 추가적으로 구현한 기능은 사용할 수 없게 되므로 원래의 기능을 다시 사용할 수 있는 방법이 필요해졌다.

4. 명시적 형변환

  • 부모 클래스의 객체자식 클래스 형태로 변환하는 것
  • 형변환을 위해서는 다음과 같이 변환할 클래스 이름을 명시적으로 지정해주어야 한다.
	ChildClass child = (ChildClass) parent;  

5. 명시적 형변환의 조건

  • 객체가 최초 생성될 때 자식 클래스 형태로 생성되고, 부모 형태로 암묵적 형변환이 된 상태를 다시 원래의 자식 클래스 형태로 되돌릴 경우에만 가능하다.
	ChildClass child1 = new ChildClass();	// 자식 클래스 형태로 생성
	ParentClass Parent = child1;			// 암묵적 형변환
	ChildClass child2 = (ChildClass)parent;	// 명시적 형변환

6. 명시적 형변환 예시

  • 가능한 경우
	Army army1 = new Army();
	Unit u = army1;
	Army army2 = (Army)u;
  • 가능한 경우
	Unit u = new Navy():
	Navy navy = (Navy)u;
  • 최초 객체 생성이 부모 형태로 만들어진 경우 불가능하다.
	Unit u = new Unit();
	Army army = (Army)u;
  • 최초 생성된 것과 다른 형식으로 변환하는 것은 불가능하다.
	Army army = new Army();
	Unit u = army;
	Navy navy = (Navy)u;	
  • 위의 두 경우 모두 문법적인 오류는 없기 때문에 이클립스에서는 에러를 검출하지 못한다.
    하지만 프로그램을 실행시켰을 경우에는 에러가 발생한다.

7. 객체배열

  • 일반 데이터 타입의 배열과 동일한 개념으로, 같은 클래스의 객체 여러 개를 그룹화 할 수 있다.
	int[] data = new int[3];
	Army[] data = new Army[3];
  • 각 경우에 대한 배열의 요소 할당 처리
    -> 일반 데이터 형은 단순히 값을 대입하지만, 객체 배열은 new를 사용하여 객체를 할당한다.
	data[0] = 1;			// 일반 데이터 형
	data[1] = 2;
	...
	data[0] = new Army();	// 객체 배열
	data[1] = new Army();
	...

8. 정리

  • 객체 형변환
    -> 같은 부모 클래스에서 파생된 서로 다른 자식 클래스의 객체들은 부모 형태로 암묵적 형변환 되어 일관된 형식으로 사용 가능하다.

  • 객체 배열
    -> 동일한 클래스의 객체는 배열로 묶어서 여러 개를 한꺼번에 제어할 수 있다.

9. 부모 클래스의 배열에 자식 클래스의 객체를 넣기

  • 배열의 생성이 부모 클래스로 지정되었을 경우, 모든 자식 클래스의 객체들은 그 배열에 포함될 수 있다.
	Unit[] unit = new Unit[3];
	unit[0] = new Army();		// 배열의 요소 할당 과정에서 암묵적 형변환이 이루어진다.
	unit[1] = new Navy();
	unit[2] = new AirForce();

10. 객체 배열의 활용

  • 일괄 처리가 가능하다.
    		for( int i=0; i<unit.length; i++ ){
    			unit[i].attack();
    		}
  • 서로 다른 객체를 부모 형태의 배열에 담기게 되면, 반복문으로 일괄처리가 가능하다.
  • 이 때 배열의 각 요소를 통해 사용하는 메서드가 Override 되어 있을 경우, 부모의 메서드가 아니라 자신이 재정의한 기능을 뜻한다.
	public class Main02 {
	public static void main(String[] args) {
		// 부대지정
		Unit[] units = new Unit[5];
		
		units[0] = new AirForce("공군1호");
		units[1] = new AirForce("공군2호");		
		units[2] = new Navy("해군1호");
		units[3] = new Army("육군1호");
		units[4] = new Army("육군2호");
		
		// 부대 일곽 공격 attack()
		// tank(), nucleus(). bombing() 각각 호출하는 로직을 추가
		for( int i=0; i<units.length; i++ ) {
			units[i].attack();
			
			if( units[i] instanceof Army ) {
				Army a = (Army)units[i];
				a.tank();
			}else if(units[i] instanceof Navy){
				Navy n = (Navy)units[i];
				n.nucleus();
			}else {
				AirForce f = (AirForce)units[i];
				f.bombing();
			}
		}
	}
}

11. 원래 기능으로 복귀하기

  • 배열의 각 요소가 확장한 기능을 사용하기 위해서는 원래의 클래스 형태로 명시적 형변환이 이루어져야 한다.
  • 하지만 반복적으로 처리되는 과정에서 몇 번째 요소가 어떤 클래스에서 최초 생성되었는지를 판단하기란 쉽지 않다.
  • intstanceof 연산자
    -> 어떤 객체에 대한 출처를 판단하여 boolean 형으로 결과를 반환한다.
	if( unit[0] instanceof Army ){
		Army temp = (Army)unit[0];
	}
  • 예시
    		if( units[i] instanceof Army ) {
    					Army a = (Army)units[i];
    					a.tank();
    				}else if(units[i] instanceof Navy){
    					Navy n = (Navy)units[i];
    					n.nucleus();
    				}else {
    					AirForce f = (AirForce)units[i];
    					f.bombing();
    				}
    			}
    		}
    
    
profile
개발자
post-custom-banner

0개의 댓글