도서/자바의 신

[도서/자바의 신] #10 자바는 상속이라는 것이 있어요

yulee_to 2022. 12. 21. 18:17

자바의 신

✔️이 글은 [자바의 신 - 이상민 지음] 도서를 바탕으로 정리한 글입니다. 


자바에서 상속(inheritance)이란?

클래스를 선언할 때 클래스 이름 뒤에 extends라는 예약어를 쓰고 그 다음에 상속받을 클래스를 써주면 해당 클래스가 상속된다.

상속이라는 건 부모와 자식 관계로 나타낼 수 있는데, 자식이 부모에 public과 proctected로 선언된 변수와 메소드를 본인이 가지고 있는 것처럼 사용할 수 있다.

 

자식 클래스 객체를 생성하면 자동으로 부모의 기본 생성자(매개변수가 없는 생성자)가 호출된다. 

확장한 클래스(자식 클래스)에는 추가적인 메소드를 만들어도 문제가 없다. 

 

상속은 코드의 간결화와 재사용성을 좋게 해주는 장점이 있다.

자바는 extends 뒤에 하나의 클래스만 올 수 있다. 즉, 하나의 클래스만 상속하는 단일 상속만 가능하다.

상속과 생성자

부모 클래스에 기본 생성자가 없는 경우 자식 클래스에서 부모 클래스의 생성자를 명시적으로 지정하는 super()를 사용해야 한다.

자식 클래스의 생성자가 실행될 때 부모의 생성자가 실행돼야 하기 때문이다. 

 

super()는 부모 클래스의 생성자를 호출하고, super.메소드이름()을 해주면 부모의 메소드를 호출한다.

자식 클래스의 생성자에는 따로 지정해주지 않아도 컴파일할 때 자동으로 super()라는 문장이 들어간다.

 

super의 괄호 안에는 호출할 부모 클래스의 생성자에 명시된 매개변수에 맞게 값을 넣어주면 된다.

super의 괄호 안에 null을 넣어주면 값이 모호하다는 컴파일 에러가 발생하므로 호출하고자 하는 생성자의 기본 타입을 넘겨주는 것이 좋다.

super를 명시적으로 지정할 때는 자식 클래스의 생성자의 가장 첫 줄에 선언되어야 한다.

메소드 Overriding

자식 클래스에서 부모 클래스에 있는 메소드와 동일하게 선언하는 것을 "메소드 overriding"이라 한다.

접근 제어자, 리턴 타입, 메소드 이름, 매개 변수 타입 및 개수가 모두 동일해야한다.

단, 접근 제어자는 조금 달라도 된다.

접근 제어자의 경우 접근 권한이 넓어지는 쪽으로 자식 클래스에서 바꿔주는건 괜찮다.

부모가 private으로 선언해줬으면 자식은 어떤 접근 제어자로 지정해줘도 상관없다.

부모 클래스에 동일한 이름의 메소드가 있는 경우 항상 나머지 요소(접근 제어자 제외)도 동일해야 한다. 바꾸면 컴파일 에러가 발생한다.

 

메소드 overriding한 메소드를 호출하면 자식의 메소드만 실행된다.

"동일하게 선언되어 있다"는 "동일한 시그니처(signature)를 가진다"고 표현한다. 시그니처는 메소드 이름, 매개변수를 의미한다.

 

Overloading vs. Overriding

  • Overloading : 확장 ( 메소드의 매개 변수들을 확장)
  • Overriding : 덮어 씀 (부모 클래스의 메소드 시그니처를 복제해 자식 클래스에서 새로운 것을 만들어 내어 부모 클래스의 기능은 무시하고, 자식 클래스에서 덮어 씀)

참조 자료형의 형 변환

부모 클래스 타입인 객체에 자식 클래스 생성자를 이용해 할당해줄 수 있다. 그 반대는 안된다.

왜냐하면 자식은 부모 클래스의 변수와 메소드를 사용할 수 있는데, 부모는 자식의 것을 모두 참조할 수도 있고 못할 수도 있기 때문이다.

 

자바 컴파일러에서는 자식 객체를 생성할 때 부모 생성자를 사용하면 안되지만 명시적으로 형변환을 하면 가능은 하다.

명시적으로 괄호 안에 자식 클래스 이름을 써주면 된다. 컴파일은 정상적으로 되지만 실행할 때 에러가 발생한다.

자식 클래스 객체를 부모 클래스로 형변환했다가 다시 자식 클래스로 형변환했을 경우엔 정상적으로 동작한다.

 

일반적으로 여러 개의 값을 처리하거나, 매개 변수로 값을 전달할 때에는 보통 부모 클래스의 타입으로 보낸다. 

객체를 할당할 때 자식의 객체를 생성해주는 방식으로 사용할 수 있다.

 

부모 클래스 배열의 타입이 부모인지 자식인지(형변환을 해줬을 수도 있으니까) 확인하려면 instanceof라는 예약어를 사용하면 된다.

객체 instanceof 클래스(타입)

이 문장은 boolean 타입의 결과를 제공한다. 

에를 들어 "부모배열[0] = new 자식 생성자();"를 해주고 "부모배열[0] instanceof 자식클래스"를 해주면 true가 반환된다.

이 부모 객체는 자식 클래스로 형변환이 가능하다.

"부모배열[0] instanceof 부모클래스"의 경우에도 true를 반환한다.

따라서 타입 점검을 할 때는 가장 하위에 있는 자식 타입부터 확인을 해야 제대로 타입 점검이 가능하다. 

Polymorphism

보통 영어론 폴리몰피즘이라고 읽고 우리말로는 다형성이라고 한다. 

부모 타입으로 선언된 객체들에 자식1 클래스, 자식2 클래스 객체를 각각 할당해주고 메소드 overriding한 메소드를 호출해주면 할당된 각 클래스의 메소드가 호출된다. 

즉, 형 변환을 하더라도, 실제 호출되는 것은 원래 객체(사용한 생성자)에 있는 메소드가 호출된다는 것이 다형성이다. 

 

자바의 자식 클래스에는 개수 제한이 없다. 

자식 클래스에서 할 수 있는 일들을 다시 정리해보자

생성자

  • 자식 클래스의 생성자가 호출되면 자동으로 부모 클래스의 기본 생성자가 호출된다. 명시적으로 super()를 사용해도 된다.
  • 부모 클래스의 생성자를 명시적으로 호출할 땐 super()를 사용한다. 

변수

  • 부모 클래스에서 private로 선언된 변수를 제외한 모든 변수가 자신의 클래스에 선언된 것처럼 사용할 수 있다.
  • 부모 클래스에 선언된 변수와 동일한 이름을 갖는 변수를 선언할 수도 있다. (권장 안함)
  • 부모 클래스에 선언되어 있지 않는 이름의 변수를 선언할 수 있다.

메소드

  • 변수처럼 부모 클래스에 선언된 메소드들이 자신의 클래스에 선언된 것처럼 사용할 수 있다.
  • 부모 클래스에 선언된 메소드와 동일한 시그니처를 사용함으로써 메소드를 overriding할 수 있다.
  • 부모 클래스에 선언되어 있지 않은 이름의 새로운 메소드를 선언할 수 있다.

정리해 봅시다

1. 상속을 받는 클래스의 선언문에 사용하는 키워드는 무엇인가요?

extends

2. 상속을 받은 클래스의 생성자를 수행하면 부모의 생성자도 자동으로 수행되나요?

YES

3. 부모 클래스의 생성자를 자식 클래스에서 직접 선택하려고 할 때 사용하는 예약어는 무엇인가요?

super

4. 메소드 Overriding과 Overloading을 정확하게 설명해 보세요.

overriding은 자식 클래스에서 부모 클래스의 메소드와 동일한 시그니처를 갖는 메소드를 선언해서 자식 클래스의 메소드만 수행되게 하는 것이고, Overloading은 같은 접근제어자, 리턴타입, 메소드이름을 갖지만 매개변수의 타입이나 개수가 다른 메소드들로 메소드에 넘겨주는 인자에 따라 맞는 메소드가 수행되게 해준다. 

5. A가 부모, B가 자식 클래스라면 A a=new B();의 형태로 객체 생성이 가능한가요?

YES

6. 명시적으로 형 변환을 하기 전에 타입을 확인하려면 어떤 예약어를 사용해야 하나요?

instanceof

7. 6에서 사용한 예약어의 좌측에는 어떤 값이, 우측에는 어떤 값이 들어가나요?

instanceof예약어의 좌측에는 확인할 클래스 객체가 들어가고, 우측에는 클래스 이름(타입)이 들어간다.

8. 6의 예약어의 수행 결과는 어떤 타입으로 제공되나요?

boolean 

9. Polymorphism이라는 것은 무엇인가요?

우리나라말로 다형성이라 하고 형 변환을 하더라도 실제 호출되는 것은 원래 객체에 있는 메소드가 호출된다는 것을 의미한다.

728x90