Inheritance (상속)

이재현·2024년 7월 25일

Java

목록 보기
8/15

🩵 클래스 간의 관계, 상속

객체지향 프로그램에서 부모 클래스의 필드와 메서드를 자식 클래스에게 물려주는 것을 상속이라 한다.
상속은 적은 양의 코드로 새로운 클래스를 작성할 수 있으며, 공통적인 코드를 관리하여 코드의 추가 및 변경이 쉽다.
즉, 상속을 통해 코드의 중복이 제거되며 재사용성이 증가하기 때문에 생산성과 유지 보수성에 유리해진다.

💙 상속

클래스 간 상속은 extends 키워드를 사용하여 정의할 수 있다.

Public class Child extends Parents { }

부모, 자식이라는 이름으로 인해 종속으로 이해하기 쉬운데, 상속은 일종의 확장의 개념으로 이해해야만 한다.

이를 보면 부모클래스에 새로운 필드 및 메서드가 추가되면 자식은 이를 상속받아 사용할 수 있다.

하지만 자식클래스에 새로운 필드와 메서드가 추가되어도 부모클래스는 어떠한 영향도 받지 않는다.

💙 클래스 간의 관계

  • 상속관계
    기존의 상위 클래스의 멤버를 내려 받아 하위 클래스의 내부에 포함시키는 관계를 말한다.
    서로 상속 관계라 하며, 하위 클래스는 상위클래스가 가진 모든 멤버를 상속받는다.

  • 포함관계
    상속처럼 클래스를 재사용하는 방법이지만 상속과는 다르게, 클래스의 멤버로 다른 클래스의 자료형의 참조변수를 선언하는 것을 말한다.

  • ❤️ 상속: “~은 ~이다.” / 포함: “~은 ~을 가지고 있다.” 로 표현한다.

💙 단일 상속과 다중 상속

Java는 다중 상속을 허용하지 않는다.
다중 상속을 허용하면 클래스 간의 관계가 복잡해지는 문제가 발생한다.

  • e.g. 자식클래스에서 상속받는 서로 다른 부모 클래스들이 같은 이름의 멤버를 가지고 있는 경우 자식클래스는 이를 구별할 수 없다!

💙 final 클래스와 final 메서드

클래스에 final 키워드를 지정하여 선언하면 최종적인 클래스가 되어서 상속할 수 없게 된다.
메서드에 final 키워드를 지정하여 선언하면 최종적인 메서드가 됨으로 더 이상 오버라이딩할 수 없는 메서드가 된다.

💙 Object

Object는 말 그대로 객체를 의미하며, 보통 Object 클래스를 의미한다.
Object 클래스는 Java 내 모든 클래스들의 최상위 부모클래스로 모든 클래스는 Object의 메서드를 사용할 수 있다.

  • e.g. Object clone(), Boolean equals(Object object), …
  • 부모 클래스가 없는 자식클래스는 컴파일러가 자동으로 Object 클래스를 상속해준다.



🩵 overriding

부모클래스로부터 상속받은 메서드의 내용을 재정의 하는 것을 오버라이딩이라 한다.
부모 클래스의 메서드를 그대로 사용 가능하지만 자식 클래스의 상황에 맞게 변경을 해야 하는 경우 오버라이딩을 사용한다.

public class SportsCar extends Car{

    String engine;
    
    public void booster() {
        System.out.println("엔진 " + engine + " 부앙~\n");
    }
    
    public SportsCar(String engine) {
        this.engine = engine;
    }
    
    @Override
    public double brakePedal() {
        speed = 100;
        System.out.println("스포츠카에 브레이크란 없다");
        return speed;
    }
    
    @Override
    public void horn() {
        booster();
    }
}

💙 오버라이딩 조건

  • 선언부가 부모 클래스의 메서드와 일치해야 한다.
  • 접근제어자를 부모 클래스의 메서드보다 좁은 범위로 변경할 수 없다.
  • 예외는 부모 클래스의 메서드보다 많이 선언할 수 없다.
💙 super & super()

Super는 부모 클래스의 멤버를 참조할 수 있는 키워드이다.

객체 내부 생성자 및 메서드에서 부모 클래스의 멤버에 접근하기 위해 사용할 수 있다.
자식 클래스 내부에서 선언한 멤버와 부모 클래스에서 상속받은 멤버와 이름이 같은 경우 이를 구분하기 위해 사용한다.

public void setCarInfo(String model, String color, double price) {

    super.model = model; // model은 부모 필드, 호출 시에 부모 클래스의 model에 값이 저장됨
    
    super.color = color; // color는 부모 필드
    
    this.price = price; // price는 자식 필드, 호출 시에 자식 클래스의 price에 값이 저장됨
}

Super()는 부모 클래스의 생성자를 호출할 수 있는 키워드이다.

객체 내부 생성자 및 메서드에서 해당 객체의 부모 클래스의 생성자를 호출하기 위해 사용될 수 있다.
자식 클래스의 객체가 생성될 때 부모 클래스들이 모두 합쳐져서 하나의 인스턴스가 생성된다.
이때, 부모클래스의 멤버들의 초기화 작업이 먼저 수행되어야 한다.

// 자식 클래스 SportsCar 생성자
public SportsCar(String model, String color, double price, String engine) {

     // this.engine = engine;이 먼저 선행되면 오류 발생
    super(model, color, price);
    this.engine = engine;
    
}

오버로딩된 부모 클래스의 생성자가 없다고 하더라도 부모 클래스의 기본 생성자를 호출해야 한다.




🩵 다형성

참조변수는 타입을 변환시킬 수 있는데, 이때 방법은 크게 2가지가 있다.

  • 자동 타입 변환

    • 부모 타입 변수 = 자식 타입 객체; 는 자동으로 부모 타입으로 변환이 일어난다.
      자식객체는 부모객체의 멤버를 상속받기 때문에 부모와 동일하게 취급될 수 있다.
  • 강제 타입 변환

    • 자식 타입 변수 = (자식 타입) 부모 타입 객체;
      부모 타입 객체는 자식 타입으로 자동으로 타입 변환이 되지 않는다.
      타입 변환 연산자를 사용해, 강제적으로 자식 타입으로 변환할 수 있다.
      다만, 자식 타입 객체가 부모 타입으로 자동 타입 변환되고 다시 자식 타입으로 변환할 때만 가능하다.
      혹은, 부모 타입 변수로 자식 타입 객체의 고유한 멤버의 사용이 필요한 경우에만 사용한다.

💙 다형성

여러가지 형태를 가질 수 있는 능력을 다형성이라 한다.
참조 변수 타입 변환을 활용해서 다형성을 구현할 수 있다.

Tire tire = new HankookTire("HANKOOK");
Tire tire = new KiaTire("KIA");

이러한 다형성은 매개변수와 반환 타입에도 적용될 수 있다.

💙 instanceof

다형성 기능으로 인해 해당 클래스 객체의 원래 클래스명을 체크하는 것이 필요하다.
이때 사용할 수 있는 명령어가 instance of 이다.
이 명령어를 통해서 해당 객체가 내가 의도하는 클래스의 객체인지 확인할 수 있습니다.

{대상 객체} instance of {클래스 이름} 와 같은 형태로 사용하면 응답값은 boolean입니다.




🩵 추상클래스

클래스가 설계도라면 추상 클래스는 미완성 설계도라 할 수 있다.

Abstract 키워드를 통해 추상 클래스를 선언할 수 있다.

추상 클래스는 추상 메서드를 포함할 수 있는데, 딱히 추상 메서드가 없어도 선언할 수 있다.

추상 클래스는 자식 클래스에 상속되어 자식 클래스에 의해서만 완성될 수 있다.

추상 클래스는 여러 개의 자식 클래스들에서 공통적인 필드나 메서드를 추출해서 만들 수 있다.

💙 추상 메서드

추상 클래스와 마찬가지로 아직 구현되지 않은 미완성 메서드이다.

동일하게 abstract 키워드를 통해 선언할 수 있고, 일반적인 메서드와는 다르게 {}이 없다.

즉, 정의만 하지 실질적인 실행 내용은 갖고 있지 않다.

💙 추상 클래스 상속

추상 메서드는 extends 키워드를 사용하여 클래스에서 상속된다.

상속받은 클래스에서 추상 클래스의 추상 메서드는 반드시 오버라이딩 되어야 한다.

public class 클래스명 extends 추상클래스명 {

@Override
   	public 리턴타입 메서드이름(매개변수, ...) {
    
// 실행문

   	}
}



0개의 댓글