본문 바로가기

JAVA

[JAVA] 클래스의 상속 2 : 오버라이딩 (자바 독학하기17)

반응형

상속을 어느 조건일때 써야 할까?

해당 책에서는 상속의 조건은 IS-A 관계일 때 사용해야 한다고 한다.

- 하위 클래스는 상위 클래스의 모든 특성을 지닌다

- 거기에 더하여 하위 클래스는 자신만의 추가적인 특성을 더하게 된다

이 예로 스마트폰은 모바일폰이다, 노트북은 컴퓨터이다, 전기자동차는 자동차이다 를 꼽는다.

 

 

자동차와 전기자동차를 상속의 개념으로 본다면

Class ElectricVehicle extends Vehicle {}

로 나타낼 수 있다.

이때 참조변수와 인스턴스 변수를 다음과 같이 구성한다.

ElectricVehicle ev = new ElectricVehicle();

그런데 Vehicle 형 참조 변수가 ElectricVehicle 인스턴스를 참조하게 할 수 있다.

Vehicle ev = new ElectricVehicle();

이를 'Vehicle 을 상속하는 ElectricVehicle 인스턴스는 Vehicle 인스턴스 이기도 하기 때문에 Vehicle 형 참조 변수는 ElectricVehicle 인스턴스를 참조할 수 있다' 라고 이해하면 된다.

다음과 같은 코드에서 

Vehicle ve1 = new ElectricVehicle();
ElectricVehicle ve2 = new ElectricVehicle();

과 같이 인스턴스를 생성하고 코드를 실행하면 line 10 ~ 14 까지의 결과로 인해 console 창이 출력된다.

그런데 이때 line 11 번의 주석을 지우면 이 코드를 에러가 발생한다.

이와 같이 상속 받은 클래스 내의 메소드 호출은 상속받은 참조변수일때만 가능하다.

이렇게 컴파일러가 설계되어있는 이유는

- 실행시간이 늦어짐을 막고 코드를 단순하게 하기 위함이다.

이는 실제 참조하는 인스턴스를 대상으로 메소드의 호출 가능성을 판단하는 것이 컴파일 속도 저하를 일으킬 수 있으므로 아예 문법적으로 막아 코드가 복잡해짐을 방지한다.

또한 참조변수가 참조하는 인스턴스의 종류에 상관없이 참조변수의 형에 해당하는 클래스와 그 클래스가 상속하는 상위 클래스에 정의된 메소드들만 호출이 가능함을 기억하자.

 

참조 변수는 대입과 형변환이 가능한데

ElectricVehicle ve2 = new ElectricVehicle();

Vehicle ve1 = ve2;

와 같은 대입이 가능하다.

그러나 

Vehicle ve1 = new ElectricVehicle();

ElectricVehicle ve2 = ve1;

은 불가능 하다.

- 자바는 참조변수의 type 정보를 기준으로 대입의 가능성을 판단한다.

라는 내용에 의한 것인데, Vehicle 을 상속하는 다른 클래스의 인스턴스일 수 있다고 판단하여 허용하지 않는다.

이런 경우

Vehicle ve1 = new ElectricVehicle();

ElectricVehicle ve2 = (ElectricVehicle)ve1;

과 같이 형 변환을 해주면 해당 대입은 가능하다.

 

이러한 참조 관계가 배열까지 이루어 지는데

Vehicle[] ve1 = new ElectricVehicle[10];
ElectricVehicle[] ve2 = new ElectricVehicle[10];

와 같이 사용될 수 있다.

 

 

상위 클래스에 정의된 메소드를 하위 클래스에서 다시 정의하는 행위를 가리켜 메소드 오버라이딩(Method Overriding)이라고 하는데 여기서 오버라이딩은 무효화 시키다 의 뜻으로 사용된다.

- 메소드 오버라이딩은 메소드의 이름, 반환형, 매개변수 선언이 같은 메소드를 정의해야 성립된다.

위 코드와 같이 ignition 메소드를 메소드 오버라이딩 하였다.

ve1.ingition 은 Vehicle 내의 ignition 메소드를 호출하여야 하지만 오버라이딩에 의해 ElectricVehicle 내의 ignition 이 호출되었다.

여러번 상속에 의한 오버라이딩이 진행되면 가장 마지막에 상속된 클래스 내의 메소드를 호출함을 기억하자.

 

오버라이딩 된 메소드를 호출하고자 할때는 super.ignition(); 과 같이 super 키워드를 sub class 에서 사용하면 호출 가능하다.

 

클래스 변수와 클래스 메소드는 오버라이딩 대상이 아닌점을 기억하고 각각의 참조변수를 사용해 호출 해야 한다.

 

 

연산자 instanceof 는 참조변수가 참조하는 인스턴스의 클래스나 참조하는 인스턴스가 상속하는 클래스를 체크한다.

 if (ve1 instanceof Vehicle)

과 같이 사용하며 ve1 이 참조하는 인스턴스가 Vehicle 의 인스턴스 이거나 Vehicle 을 상속하는 클래스의 인스턴스이면 true 를 반환하고 아니라면 false 를 반환한다.

다음과 같이 해당 참조 변수가 해당 클래스나 상속하는 클래스임을 체크할 수 있다.

책에서는

- 연산자 instanceof 는 명시적 형 변환의 가능성을 판단해주는 연산자이다.

라고도 할 수 있으며

(ElectricVehicle)ve1.ignition 과 같이 표현할 수 있는 가능성을 보여주는 연산자라고 한다.

반응형