객체 지향의 특성 (2) : 상속 (~은 ~이다. is-a)하위 클래스가 생성 되는 과정super 키워드형 변환(업캐스팅)다운 캐스팅 & instanceof오버라이딩(overriding)메서드 어떻게 호출되고 실행?가상 메서드의 원리C++ 에서 Virtual 키워드(참고)객체 지향의 특성 (3) : 추상화객체 지향의 특성 (4) : 다형성추상 클래스(abstract class) - abstract템플릿 메서드 패턴(프레임워크에서 많이 쓰는 패턴) - finalfinal 예약어
객체 지향의 특성 (2) : 상속 (~은 ~이다. is-a)
- 상속 문법(B클래스가 A를 상속받을때)
class B extends A
- 자바는 단일 상속만 지원함
- 상속에 대한 오해 : 공통된 기능을 여러 객체에게 전달하고 싶을 때. 이때 사용하는 것이 아닌 추상과 구체의 관계임
하위 클래스가 생성 되는 과정
- 하위 클래스를 생성하면 상위 클래스가 먼저 생성됨
- 하위 클래스의 생성자가 실행 될 때, 상위 클래스의 생성자가 실행되는
super()
를 compiler가 자동으로 넣어줌
super 키워드
- 하위 클래스에서 명시적으로 상위 클래스의 생성자를 호출하지 않으면 super()가 호출 됨 (이때 반드시 상위 클래스의 기본 생성자가 존재 해야 함)
- 상위 클래스에 기본 생성자가 없는 경우(다른 생성자가 있는 경우 - 기본생성자 안만들어주니까) 하위 클래스에서는 생성자에 super를 이용하여 명시적으로 상위 클래스의 생성자 호출해야함
형 변환(업캐스팅)
Customer vc = new VIPCustomer(12345, "noname");
- 변수의 타입은 상위 클래스로 선언하고 하위 클래스의 instance를 할당함
- 실제 접근 가능한 변수, 메소드는 Customer의 것들만 접근 가능함
- 하위 클래스는 상위 클래스의 타입을 내포하고 있으므로 상위 클래스로의 묵시적 형 변환이 가능함
- 상속받은 여러 하위클래스들을 상위의 클래스로 선언함으로써 공통된 변수로 관리할수있다는 것이 장점?
다운 캐스팅 & instanceof
- 업캐스팅된 클래스를 다시 원래의 타입으로 형 변환
- 하위 클래스로의 형 변환은 명시적으로
- instanceof를 사용하는 것은 복잡한 스위칭 로직이 뒤 따를 것을 암시하는 것으로 좋지 않은 디자인에서 쓰인다고 함.
equals(Object o)
여기에서 주로 사용 - 차라리 대신에 Strategy pattern을 사용해라 — [ Stackoverflow : Why should and shouldn’t use instanceof]
Customer vc = new VIPCustomer(); // 묵시적 VIPCustomer vCustomer = (VIPCustomer)vc; // 명시적 if (vc instanceof Customer) {}
오버라이딩(overriding)
- 상위 클래스에 정의된 메서드 하위클래스에서 동일한 이름으로 재정의
- @Override 라는 annotation을 붙임
@Override public int calcPrice(int price){ ... }
메서드 어떻게 호출되고 실행?
- 메서드(함수)의 이름은 주소값을 나타냄
- 메서드는 명령어의 set이고 프로그램이 로드되면 메서드 영역(코드 영역)에 명령어 set이 위치
- ⇒ 다른 인스턴스더라도 같은 메서드의 코드는 같으므로 같은 메서드가 호출됨
- 인스턴스가 생성될때, 변수는 힙 메모리에 따로 생성되지만, 메서드 명령어 set은 처음 한번만 로드
가상 메서드의 원리
- static, final, private method는 가상메서드가 될 수 없음(override를 할 수가 없기 떄문에)
- 가상 메서드 테이블에서 해당 메서드에 대한 address를 가지고 있음

- 가상 메서드가 x ⇒ Customer의 calcPrice() call
- 가상메소드 o ⇒ 가상 메서드 테이블에서 해당 메서드에 대한 address를 가지고 있기에 VIPCustomer의 calcPrice를 call()
- java는 기본이 가상메서드
Customer customer2 = new Customer(); customer2.calcPrice(); // Customer.calcPrice 호출 Customer customer = new VIPCustomer(); customer.calcPrice(); // VIPCustomer.calcPrice호출
C++ 에서 Virtual 키워드(참고)
class Parent{ public: Parent(){}; ~Parent(){}; void foo(){ std::cout << "parent!!"; }; } class Child : public Parent{ public: Child(){}; ~Child(){}; void foo(){ std::cout<< "child!!!"; }; }; int main(){ Parent *p = new Child(); (p) -> foo(); return 0; }
- 해당 코드의 실행 결과는 parent!! 가 출력됨
- 그 이유는, 컴파일러가 포인터의 타입을 보고 타입에 맞는 메소드를 찾아주기 때문
- 그러나 부모의 foo 메소드 앞에 virtual이라는 키워드를 붙이면 child의 foo 메소드가 호출됨. 즉 인스턴스의 타입를 보고 메서드를 호출함
객체 지향의 특성 (3) : 추상화
객체 간의 관계에서 상위에 있는 것이 항상 하위보다 추상적이어야 함
객체 지향의 특성 (4) : 다형성
Animal hAnimal = new Human(); Animal tAnimal = new Tiger(); Animal eAnimal = new Eagle(); AnimalTest test = new AnimalTest(); test.moveAnimal(hAnimal); test.moveAnimal(tAnimal); test.moveAnimal(eAnimal); public void moveAnimal(Animal animal){ animal.move(); }
- 형(type)이 많다 = 다형성
- Human, Tiger, Eagle가 Animal 클래스를 상속받아 move라는 함수를 override해서 만들었을때 위와 같이 Animal class로 instance형변환을 하여 같은 method를 call했을때 다른 implementation이 되도록 할 수 있음
추상 클래스(abstract class) - abstract
- 구현 코드 없이 메서드의 선언만 있는 추상 메서드를 포함한 클래스
- 메서드 선언 : 반환타입, 메서드이름, 매개변수로 구성
- 메서드 정의 : 메서두 구현과 동일한의미. 구현부(body)를 가짐
- abstract 메서드를 포함하면 abstract class여야함
- abstract 메서드를 가진 클래스를 상속 받으면 그 method를 구현해주어야함. 아니라면 상속받은 클래스도 abstract 클래스가됨
- abstract class → instance 생성 불가. 상속을 하기 위해서 만든 클래스
- abstract class로 instance를 생성하는 것은 abstract class의 instance를 생성하는 것이 아닌 abstract class의 anonymous subclass의 instance를 생성하는 것임!
new ParameterizedTypeReference<SearchLocalRes>(){};
→ 여기서 ParameterizedTypeReference는 abstract class인데 이를 생성했다? 추상클래스를 만든것이 아니라 추상 클래스를 상속하는 anonymous subclass를 만든 것!
int add(int x, int y); // 선언 int add(int x, int y){ ... } // 구현부가 있음, 추상 메서드 아님

- 기울임 글씨 → abstract class & abstract method
템플릿 메서드 패턴(프레임워크에서 많이 쓰는 패턴) - final
- 라이브러리(eg. jdk) : 기능들을 가져와서 흐름은 개발자가 구현하는것
- 프레임워크(eg. android) : 흐름이 다 정해져 있음. 틀이 만들어져 있고 비워져있는 구멍(세부적인 기능)들을 우리가 채워넣는것
- 추상 클래스로 선언된 상위 클래스에서 템플릿 메서드(final)를 활용하여 전체적인 흐름을 정의하고 하위 클래스에서 다르게 구현되어야 하는 부분은 추상 메서드로 선언하여 하위 클래스에서 구현하도록 함
- final로 선언하여 하위 클래스에서 재정의 할 수 없게 함
public abstract class Car { public abstract void drive(); // 추상메서드 public abstract void stop(); public void startCar() { System.out.println("시동을 켭니다"); } public void turnOff() { System.out.println("시동을 끕니다."); } final public void run() { // 템플릿 메서드 - 흐름을 정의 startCar(); drive(); stop(); turnOff(); } }
final 예약어
- final 변수: 값이 변경될 수 없는 상수
- final 메서드 : 하위 클래스에서 재정의 할 수 없는 메서드
- final class : 상속할 수 없는 클래스