상속은 부모 클래스를 상속받은 자식 클래스가 기능을 물려받는 걸 의미한다. 아래 예제 코드를 보자.
Bus
클래스는 아무것도 선언되지 않았지만, Car
클래스를 상속받고 있으며, passenger
클래스에서 Bus
클래스의 인스턴스를 생성해서 Car
클래스의 메서드 run()
을 실행하는 코드이다.
Car.java
1 | package devandy.java.inheritance; |
Bus.java
1 | package devandy.java.inheritance; |
passenger.java
1 | package devandy.java.inheritance; |
실행결과는 다음과 같다.
1 | 탑승하다. |
아무것도 선언하지 않은 빈껍데기 일뿐인 Bus
클래스의 인스턴스를 생성했는데, 인스턴스에서 메서드를 호출할 수 있었다.
Bus
클래스가 Car
클래스를 상속받으면서 Car
클래스에 선언된 기능(메서드)들도 사용할 수 있게된 것이다.
상속을 활용하면 중복코드를 줄일 수 있는 장점이 있다. 또 이런 특징때문에 객체지향 프로그래밍의 핵심적인 개념으로 사용되기도 한다.
추가로 서브 클래스에서 수퍼 클래스의 기능을 직접 호출하고 싶을땐 super
키워드를 통해 사용할 수 있다. 위의 코드에서 passenger 클래스에서 run()
을 호출하는 것이 아니라 Bus 클래스에서 run()
을 호출하고 싶다면, 아래처럼 작성하면 된다.
1 | package devandy.java.inheritance; |
위의 예제코드를 활용하여 생성자를 추가하는 것으로 조금 변형을 해보았다.Bus
클래스에서 생성자를 만들어보았다. 이 생성자는 숫자를 파라미터로 받아서 number+" 번 버스"
라는 문장을 출력한다. passenger
클래스에서 숫자를 인자값으로 넣는 인스턴스를 생성후, run()
을 실행했다.
Car.java
1 | package devandy.java.inheritance; |
Bus.java
1 | package devandy.java.inheritance; |
passenger.java
1 | package devandy.java.inheritance; |
실행결과이다.
1 | 1415번 버스 탑승하다. |
위의 프로그램이 JVM에서 작동하는 순서는 다음과 같다.
1 | Bus b = new Bus(1415); |
우선 passenger
클래스의 main()
이 실행되고, main()
에서 호출한 Bus
클래스의 생성자가 실행된다.
1 | b.run(); |
그리고 인스턴스의 메서드를 실행하기 위해 인스턴스의 클래스 타입인 Bus
클래스가 호출되고, 찾는 메서드가 Bus
클래스에 없으므로 수퍼 클래스인 Car
클래스에서 찾아서 호출된다.
예제코드로 확인해보자.
Car.java
1 | package devandy.java.inheritance; |
Bus.java
1 | package devandy.java.inheritance; |
CarExam.java
1 | package devandy.java.inheritance; |
실행결과는 다음과 같다.
1 | Super 클래스, Car 생성자입니다. |
Bus
클래스의 인스턴스를 선언했을뿐인데, Bus
클래스의 수퍼 클래스인 Car
클래스의 생성자가 먼저 호출되고, Bus
클래스의 생성자가 호출된걸 확인할 수 있다.
서브 클래스에 해당하는 객체를 호출하면, JVM에서 자동으로 해당 객체의 수퍼 클래스를 호출하는데, 이는 **JVM에서 서브 클래스에 super()
를 자동으로 생성**했기 때문이다.
위의 코드는 정확히 아래의 코드와 같다.
달라진 거라곤 서브 클래스에 해당하는 Bus
클래스의 생성자에 super()
를 추가한 것 뿐이다.
아까는 수퍼 클래스인 Car
클래스의 생성자가 기본 생성자였기 때문에 프로그래머가 super()
를 생략하더라도, JVM에서 서브클래스에 자동으로 super()
를 생성해주면서 수퍼 클래스의 생성자를 먼저 호출할 수 있었다.
반대로 수퍼 클래스의 생성자가 기본 생성자가 아닐 경우에는 프로그래머가 임의로 super()
를 작성해주어야 한다.
1 | Implicit super constructor Car() is underfined. Must explicityly invoke another constructor |
수퍼 클래스의 생성자를 기본 생성자에서 파라미터를 받는 생성자로 바꾸자 위와 같은 경고 메세지가 출력되었다.
수퍼 클래스인 Car()
가 정의되지 않았으며, 다른 생성자를 반드시 명쾌하게 적용하라고 한다.
서브 클래스인 Bus
클래스의 생성자 내부에 임의로 super()
를 생성하고, 여기에 수퍼 클래스의 생성자에 주입할 수 있는 문자열을 인자값으로 넣어주었다. 그리고 서브 클래스에서 입력받은 인자값을 출력할 수 있도록 Car 클래스의 생성자 속 출력문도 수정을 해주었다. 정상적으로 출력된 걸 확인할 수 있다.
이를 통해, 수퍼 클래스의 생성자가 기본 생성자일 경우는 프로그래머가 따로 호출하지 않아도 JVM에서 서브클래스의 생성자에 super()
를 생성해주어 서브클래스를 호출하는 것만으로 수퍼 클래스까지 함께 호출할 수 있었다. 또 수퍼 클래스의 생성자가 기본생성자가 아닐 경우에는 프로그래머가 서브 클래스의 생성자 내부에 super()
를 명시함으로써 마찬가지로 수퍼클래스를 호출할 수 있었다.