카테고리 없음

이것이 자바다 신용권의 Java 프로그래밍 정복 - 7장

wlsdnr143 2022. 8. 30. 16:49

7장

* 해당 글은  "이것이 자바다 신용권의 Java 프로그래밍 정복"을 기반으로 작성하였으며

책의 모든 목차를 다루는 것은 아니기에 내용중에 목차에서 빠진 부분도 있다는점 참고바랍니다.


 

7장 목차

  • 7.1 상속 개념
  • 7.2 클래스 상속
  • 7.3 부모 생성자 호출
  • 7.4 메소드 재정의
  • 7.5 final 클래스와 final 메소드
  • 7.6 protected 접근 제한자
  • 7.7 타입 변환과 다형성
  • 7.8 추상 클래스

7.1 상속 개념

6장에서 상속에 대해서 잠깐 얘기할때 정말 좋은 놈이라고도 얘기했던,

상속에 대해서 자세히 알아보자.

 

상속은 말 그대로 현실세계에서 부모가 자식에게 물려주듯이,

프로그램상에서도 부모가 가진 필드, 메소드를 물려줄 수 있다.

 

그렇기에 상속이 가지는 장점에는 두 가지가 있다.

  1. 코드의 중복을 줄여준다.
    이미 잘 개발된 클래스를 재사용해서 새로운 클래스를 만들기 때문에 코드의 중복을 줄여준다.
  2. 유지 보수 시간을 최소화시켜준다.
    부모 클래스의 수정으로 모든 자식 클래스들의 수정 효과를 가져오기 때문에 유지 보수 시간을 최소화시켜준다.

 

 

하지만 상속을 한다 해도 부모 클래스의 모든 필드와 메소드들을 물려주는 것은 아니다.

6장에서 배웠던 private 접근 제한을 갖는 필드와 메소드는 상속 대상에서 제외된다.

 


7.2 클래스 상속

현실에서 상속은 부모가 자식을 선택해서 물려주지만 프로그램에서는 반대이다.

자식이 부모를 선택한다.

 

또한 자바에서는 다른 언어와 달리 다중 상속을 허용하지 않는데,

그럼 여기서 궁금한게 생긴다.

다른 언어는 다중 상속을 허용하는데 왜 자바는 다중 상속을 허용하지 않는 것일까?

궁금해서 검색해보니 이는 "다이아몬드 문제" 때문이라고 한다.

 

위 사진에서 각 알파벳을 클래스라고 생각해보면,

아래 코드와 같이 표현할 수 있다.

class A {
    void myMethod(){
        System.out.println("I`m A");
    }
}

class B extends A {
    @Override
    void myMethod(){
        System.out.println("I`m B");
    }
}

class C extends A {
    @Override
    void myMethod(){
        System.out.println("I`m C");
    }
}

class D extends B, C{
    @Override
    void myMethod() {
        super.myMethod(); //I`m B or I`m C
    }
}

위 코드를 보면 B, C 는 A의 자식 객체이다.

그리고 B,C 각각 myMethod를 오버라이드로 재정의 해주었다.

 

마지막에 D 에서 B,C 를 상속받고 부모의 myMethod를 실행하면

어떤 myMethod가 실행되어야하는가? 라는 문제가 바로 다이아몬드 문제이다.

 

둘 중 어떤 메소드가 실행되어야하는지 알 수 없으므로 자바는 다중 상속을 허용하지 않은 것이다.


7.3 부모 생성자 호출

부모 없는 자식 없듯이

자바에서 자식 객체를 생성하면, 

부모 객체가 먼저 생성되고 자식 객체가 그 다음에 생성된다.

 

모든 객체는 클래스의 생성자를 호출해야만 생성되며, 부모 객체도 예외는 아니다.

그렇다면 부모 객체를 생성하기 위해 부모 생성자를 어디서 호출한 것일까?

부모 생성자는 자식 생성자의 맨 첫 줄에서 호출된다.

만약 생성자가 명시적으로 선언되지 않았다면 

컴파일러는 다음과 같은 기본 생성자를 생성해 낸다.

public Bang(){
	super();
}

위 코드에서 super(); 은 부모의 기본 생성자를 호출하는 코드이다.


7.4 메소드 재정의

메소드 오버라이딩은 상속된 메소드의 내용이 자식 클래스에 맞지 않을 경우,

자식 클래스에서 동일한 메소드를 재정의하는 것을 말한다.

 

메소드 오버라이딩을 할 때에는 다음과 같은 규칙이 있다.

  • 부모의 메소드와 동일한 시그니처(리턴 타입, 메소드 이름, 매개 변수 리스트) 를 가져야 한다.
  • 접근 제한을 더 강하게 오버라이딩 할 수 없다.
  • 새로운 예외를 throws 할 수 없다.

7.4.2 부모 메소드 호출(super)

자식 클래스에서 부모 클래스의 메소드를 오버라이딩하게 되면, 부모 클래스의 메소드는 숨겨지고

오버라이딩된 자식 메소드만 사용된다.

 

근데 부모 클래스의 메소드를 호출해야 하는 상황도 있을텐데 이럴땐 어떻게 하면 좋을까

다 방법이 있다.

 

바로 super 키워드를 붙이는 것이다.

 

super는 부모 객체를 참조하고 있기 때문에 부모 메소드에 직접 접근할 수 있다.

super.부모메소드();

7.5 final 클래스와 final 메소드

final 키워드는 클래스, 필드, 메소드 선언 시에 사용할 수 있다. 

final을 클래스와 메소드 선언 시에 사용하면 상속과 관련이 있다.

  • final 클래스는 상속이 불가
  • final 메소드는 오버라이딩이 불가

7.7 타입 변환과 다형성

자동 타입 변환의 개념은 자식은 부모의 특징과 기능을 상속받기 때문에,

부모와 동일하게 취급될 수 있다.

 

그렇다면 왜 자동 타입 변환이 필요할까?

다형성과 관계가 있다고는 하지만 책을 읽어봐도 타입 변환과의 다형성과의 관계가 명확하게 이해가 되지 않는다.

관련 자료들을 더 찾아보고 이해를 해봐야겠다. - 2022/08/30


7.8 추상 클래스

객체를 직접 생성할 수 있는 클래스를 실체 클래스라고한다면,

이 클래스들의 공통적인 특성을 추출해서 선언한 클래스를 추상 클래스라고 한다.

 

실체 클래스와 추상 클래스는 상속의 관계를 가지고 있다.

추상 클래스가 부모이고 실체 클래스가 자식으로 구현되어,

실체 클래스는 추상 클래스의 모든 특성을 물려받고, 추가적인 특성을 가질 수 있다.

 

추상 클래스는 new 연산자를 통해서 인스턴스를 생성시키지 못한다.

 

그렇다면 이러한 추상 클래스의 용도는 무엇일까?

  1. 실체 클래스들의 공통된 필드와 메소드의 이름을 통일할 목적
  2. 실체 클래스를 작성할 때 시간을 절약