상속을 어느 조건일때 써야 할까?
해당 책에서는 상속의 조건은 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 과 같이 표현할 수 있는 가능성을 보여주는 연산자라고 한다.
'JAVA' 카테고리의 다른 글
[JAVA] 인터페이스와 추상 클래스 (자바 독학하기19) (0) | 2021.07.13 |
---|---|
[JAVA] 클래스의 상속 3 : 상속의 목적 (자바 독학하기18) (0) | 2021.07.12 |
[JAVA] 클래스의 상속 1 : 기본 (자바 독학하기16) (0) | 2021.07.05 |
[JAVA] 배열 (Array) (자바 독학하기15) (0) | 2021.06.30 |
[JAVA] 콘솔 입·출력 (자바 독학하기14) (0) | 2021.06.28 |