도찐개찐

[JAVA] 상속(Inheritance) 본문

JAVA

[JAVA] 상속(Inheritance)

도개진 2022. 7. 6. 15:11

"상속"을 공부하기전 사전에 알아두면 좋은 지식

인터페이스(Interface) :

사전적 의미로는 “전기 신호의 변환(變換)으로 중앙 처리 장치와 그 주변 장치를 서로 잇는 부분. 또는, 그 접속 장치.”

USB, C-type, 콘센트, 전구 와 같은 것을 떠올려 주시면 됩니다.

각 기관 및 협회등에서 설정한 규격에 맞춘 설계도(어떠한 동작을 설계하지는 않음)를 제공하고 일반 기업에서 판매목적으로

해당 규격의 상품에 특별한 기능을 구현하여 판매 함으로써 상품의 규격화등을 통한 비용 절감, 편의, 개발기간 단축등의 이점을 볼수 있습니다.

(ex : 예전 아이폰에선 5핀, 8핀등의 자체적인 접속장치를 사용 하여 비규격에 따른 불편함을 느꼇습니다.)

개발 부분에서는 프레임워크, 라이브러리, 프로젝트 리더급 개발자들이 기능이 없는 규격을 정하여 해당 규격에 맞춘 프로그래밍을 진행 할 수 있도록 인터페이스를 설계 한다.

인터페이스를 상속(implements) 받아 해당 규격에서 선언한 메소드에 자손클래스만의 특별한 기능으로 구현한다.

인터페이스 메소드 특징 매개변수, 리턴 자료형 구조를 규격화 함. 인스턴스 변수 생성 불가.

추상화 클래스(Abstract Class) :

인터페이스와 달리 추상화클래스 상속(extends)을 받아 abstract로 선언 된 메소드(기능 구현 불가)는 강제적으로 개발자가 오버라이드 해서 기능을 구현해야 합니다.

인스턴스 변수(부모 클래스 인스턴스 변수 사용 가능), 일반 메소드 사용(override 하지 않고 부모 클래스 메소드 사용가능)

 

인터페이스, 추상화 클래스 이점 : 단순 규격을 공식화 함으로써 하위 개발자들이 프로그램을 개발함에 있어 규격에 맞춘 개발을 하게 유도하고 동일 규격에 맞춘 클래스들을 상황에 따라 분리 또는 끼워 맞추게 하게 함으로써 유지보수 부분의 이점을 취하기 위한 목적이 강함.

(ex : 전구 동일 규격의 전구를 이걸끼우면 백색전구, 저걸끼우면 황색전구)

 

인터페이스, 추상화 클래스 이점 : 단순 규격을 공식화 함으로써 하위 개발자들이 프로그램을 개발함에 있어 규격에 맞춘 개발을 하게 유도하고 동일 규격에 맞춘 클래스들을 상황에 따라 분리 또는 끼워 맞추게 하게 함으로써 유지보수 부분의 이점을 취하기 위한 목적이 강함.

(ex : 전구 동일 규격의 전구를 이걸끼우면 백색전구, 저걸끼우면 황색전구)

 

관련 포스팅

 

[JAVA] 추상화(Abstract) VS 인터페이스(Interface)

추상 클래스(Abstract) 간단히 말하면... 클래스를 설계도라 하면, 추상 클래스는 미완성 설계도에 비유할 수 있다. (여기서 클래스가 미완성이라는 것은 추상 메서드를 포함하고 있다는 의미이다.

dev-truly.tistory.com

 

상속이란?

자바에는 상속(Inheritance)이라는 개념이 존재합니다.

쉽게 말해 부모 클래스(상위 클래스)와 자식 클래스(하위 클래스)가 있으며, 자식 클래스는 부모 클래스를 선택해서, 그 부모의 멤버를 상속받아 그대로 쓸 수 있게 됩니다.

상속을 하는 이유는 간단합니다. 이미 마련되어 있던 클래스를 재사용해서 만들 수 있기 때문에 효율적이고, 개발 시간을 줄여주게 됩니다.

상속을 하더라도 자식 클래스가 부모의 모든 것들을 물려받는 것은 아닙니다.

  • 부모 클래스의 private 접근 제한을 갖는 필드 및 메소드 자식이 물려받을 수 없습니다.
  • 부모와 자식 클래스가 서로 다른 패키지에 있다면, 부모의 default 접근 제한을 갖는 필드 및 메소드도 자식이 물려받을 수 없습니다.
    (default 접근 제한은 ‘같은 패키지에 있는 클래스’만 접근이 가능하게끔 하는 접근 제한자이기 때문입니다.)
  • 그 이외의 경우는 모두 상속의 대상이 됩니다.

클래스 상속

상속받고자 하는 자식 클래스명 옆에 extends 키워드를 붙이고, 상속할 부모 클래스명을 적습니다.
자바는 다중 상속을 허용하지 않으므로, extends 뒤에는 하나의 부모 클래스만 와야 합니다.

 
public Class Parent{ .... }; // 부모 클래스
public Class Child extends parent { .... }; // 자식 클래스

다음은 코드 예시입니다. (ParentBook 클래스를 ChildBook 클래스가 상속, 둘은 같은 패키지로 가정)

public class ParentBook{
  String name; //필드
  int price;

    public void Print(){ // 메소드
      System.out.println("책의 이름과 가격 : "+name+" "+price);
    }
}
 
 
public class ChildBook extends ParentBook{
  	ChildBook (String name, int price){ // 생성자
    this.name = name;  //  ChildBook이 ParetBook의 필드를 상속받아서 가능한 선언
    this.price = price; //
}

public static void main (String[] args){
      ChildBook Child = new ChildBook("나의 라임오렌지 나무", 10000);
      System.out.print("[구현 결과 1] ");
      Child.Print();
}

[구현 결과 1] 책의 이름과 가격 : 나의 라임오렌지 나무 10000

ChildBook 클래스가 ParentBook의 필드와 메소드를 상속받았습니다.
그러므로 ChildBook 클래스 내에 따로 필드나 메소드가 선언되어 있지 않았는데도,
생성자의 this.name 선언이나, main 메소드의 Child.Print() 가 컴파일 에러가 나지 않게 됩니다.

어렵게 생각하지 마시고 부모의 필드와 메소드를 그대로 가져다 쓴다고 생각하시면 편합니다.


부모 생성자의 호출 : super(…);

자바에서는 자식 객체를 생성하면, 부모 객체를 먼저 생성한 후, 자식 객체가 그 다음에 생성됩니다.

위에서 살펴보았던 코드에서는 따로 부모 객체를 생성하는 과정이 코드상에는 구현되어 있지 않았는데,
사실 내부적으로는 부모 객체 생성 후, 자식 객체가 생성되는 것이었습니다.

 

객체는 생성자를 호출해야만 생성되는데, 부모 객체를 생성할 때 부모 생성자를 어디서 호출할까요? 계속 위에서 살펴보았던 코드로 설명을 하겠습니다.

일단 생성자는 ‘명시적인 생성자 선언’이 없다면, 컴파일러는 알아서 기본 생성자를 생성하여 호출합니다.

위에서 봤던 코드에서는 부모 클래스(ParentBook)는 명시적 생성자 선언이 없었고, 자식 클래스(ChildBook)는 명시적 생성자 선언이 존재합니다.

그러면 이 때 부모 클래스의 생성자 선언은, 자식 클래스의 생성자 선언 내부에 맨 첫줄에 super(); 라고 생성됩니다.

부모의 기본 생성자 선언을 포함해서 명시적 생성자 선언이 없었으므로, 컴파일러가 super(); 를 알아서 생성합니다. 그리고 그 super(); 는 부모 클래스의 기본 생성자를 컴파일러가 호출하는 것입니다.

앞으로 ‘super’ 키워드는 부모 클래스(객체)를 나타내는 것임을 기억하면 됩니다.

그렇다면 부모에게 기본 생성자는 없고, 매개 변수가 있는 명시적 생성자만 있다면 어떻게 될까요?

자식 클래스에서는 반드시 생성자 내부 첫줄에 super( 매개값 , 매개값, …); 과 같이 선언해 주어야 합니다.\

컴파일러는 기본 생성자만 담당해 주기 때문입니다.

public class ParentBook{
    String name; //필드
    int price;

    public ParentBook (String name, int price){ // 부모의 생성자가 있는 경우
        this.name = name;
        this.price = price;
    }
    public void Print(){ // 메소드
    	System.out.println("책의 이름과 가격 : "+name+" "+price);
    }
}
public class ChildBook extends ParentBook{
    ChildBook (){ // 자식 생성자
    	super("나의 라임오렌지 나무", 10000); // 반드시 자식 생성자 첫줄에 선언
    }

    public static void main (String[] args){
        ChildBook Child = new ChildBook();
        System.out.print("[구현 결과 2] : ");
        Child.Print();
    }
}
 
 

[구현 결과 2] 책의 이름과 가격 : 나의 라임오렌지 나무 10000

만일 부모에게 매개변수를 포함한 명시적 생성자 선언이 있었는데, 자식 생성자에서 super 를 통하여 호출해주지 않았을 경우 컴파일 에러가 납니다.

또한, 앞에서도 말했다시피 반드시 자식 생성자 내부의 첫 줄에 super(…..); 를 써야만 컴파일 에러가 나지 않습니다.

 

출처 : https://chanhuiseok.github.io/posts/java-1/

728x90

'JAVA' 카테고리의 다른 글

[JAVA] instanceof  (0) 2022.07.07
[JAVA] 클래스 형변환  (0) 2022.07.07
[JAVA] 초기화 블럭(initialization block)  (0) 2022.07.06
[JAVA] 클래스변수, 인스턴스변수, 지역변수  (0) 2022.07.06
[JAVA] static, final, static final  (0) 2022.07.06
Comments