회원가입

상속 - 기능 추가 / 메서드 오버라이딩

Beany 2024-09-25

ChatGPT 요약

이번 블로그 포스트에서는 상속과 기능 추가, 그리고 메서드 오버라이딩에 대해 다루고 있습니다. 상속을 통해 부모 클래스의 기능을 자식 클래스에 추가할 수 있으며, 새로운 수소차 클래스를 만들어 수소를 충전하는 기능을 추가하는 방법을 소개하고 있습니다. 또한, 메서드 오버라이딩을 통해 부모 클래스의 메서드를 자식 클래스에서 다르게 재정의하는 방법을 안내하고 있습니다. 요약이 필요하면 계속 말해주세요.

상속과 기능 추가

이번에는 상속 관계의 장점을 알아보기 위해, 상속 관계에 다음 기능을 추가해보자.

  • 모든 차량에 문열기(openDoor()) 기능을 추가해야 한다.
  • 새로운 수소차(HydrogenCar)를 추가해야 한다.
    • 수소차는 fillHydrogen() 기능을 통해 수소를 충전할 수 있다.

 

기존 코드를 유지하기 위해 ex3 패키지를 새로 만들자

package ex3;

public class Car {
    public void move() {
        System.out.println("Car move");
    }
    
    public void openDoor() {
        System.out.println("Car open door");
    }
}

모든 차량에 문열기 기능을 추가할 때는 상위 부모인 Car 에 openDoor() 기능을 추가하면 된다.
이렇게 하면 Car 의 자식들은 해당 기능을 모두 물려받게 된다.
만약 상속 관계가 아니었다면 각각의 차량에 해당 기능을 모두 추가해야 한다.

 

package ex3;

public class ElectricCar extends Car {
    public void charge() {
        System.out.println("Electric car charged");
    }
}

 

package ex3;

public class GasCar extends Car {
    public void fillUp() {
        System.out.println("Gas car is filled up");
    }
}

기존 코드와 같다.

 

package ex3;

public class HydrogenCar extends Car {
    public void fillHydrogen() {
        System.out.println("Fill Hydrogen");
    }
}

수소차를 추가했다. Car 를 상속받은 덕분에 move(), openDoor() 와 같은 기능을 바로 사용할 수 있다.
수소차는 전용 기능인 수소 충전(fillHydrogent()) 기능을 제공한다.

 

package ex3;

public class CarMain {
    public static void main(String[] args) {
        ElectricCar electricCar = new ElectricCar();
        electricCar.move();
        electricCar.charge();
        electricCar.openDoor();

        GasCar gasCar = new GasCar();
        gasCar.move();
        gasCar.fillUp();
        gasCar.openDoor();

        HydrogenCar hydrogenCar = new HydrogenCar();
        hydrogenCar.move();
        hydrogenCar.fillHydrogen();
        hydrogenCar.openDoor();
    }
}
Car move
Electric car charged
Car open door
Car move
Gas car is filled up
Car open door
Car move
Fill Hydrogen
Car open door

기능을 추가하고 클래스를 확장했다. 상속 관계 덕분에 중복은 줄어들고, 새로운 수소차를 편리하게 확장(extend)한 것을 알 수 있다.

 

 

상속과 메서드 오버라이딩

부모 타입의 기능을 자식에서는 다르게 재정의 하고 싶을 수 있다.
예를 들어서 자동차의 경우 Car.move() 라는 기능이 있다.  이 기능을 사용하면 단순히 "Car move" 라고 출력한다. 전기차의 경우 보통 더 빠르기 때문에 전기차move() 를 호출한 경우에는 "EletricCar move fast" 라고 출력을 변경하고 싶다.

이렇게 부모에게서 상속 받은 기능을 자식이 재정의 하는 것을 메서드 오버라이딩(Overriding)이라 한다.

 

package extends1.overriding;

public class Car {
    public void move() {
        System.out.println("Car move");
    }

    public void openDoor() {
        System.out.println("Car open door");
    }
}

 

전기차 부분만 Override 를 붙이자.

package extends1.overriding;

public class ElectricCar extends Car {
    @Override
    public void move() {
        System.out.println("ElectricCar move fast");
    }
    
    public void charge() {
        System.out.println("Electric car charged");
    }
}

ElectricCar 는 부모인 Car move() 기능을 그대로 사용하고 싶지 않다. 메서드 이름은 갇지만 새로운 기능을 사용하고 싶다.
그래서 ElectricCar move() 메서드를 새로 만들었다.

이렇게 부모의 기능을 자식이 새로 재정의하는 것을 메서드 오버라이딩이라 한다.

이제 ElectricCar move() 를 호출하면 Car move() 가 아니라 ElectricCar move() 가 실행된다.

package extends1.overriding;

public class CarMain {
    public static void main(String[] args) {
        ElectricCar electricCar = new ElectricCar();
        electricCar.move();
        electricCar.charge();
        electricCar.openDoor();

        GasCar gasCar = new GasCar();
        gasCar.move();
        gasCar.fillUp();
        gasCar.openDoor();
    }
}
ElectricCar move fast
Electric car charged
Car open door
Car move
Gas car is filled up
Car open door

 

@Override

@ 이 붙은 부분을 애노테이션이라 한다. 애노테이션은 주석과 비슷한데, 프로그램이 읽을 수 있는 특별한 주석이라 생각하면 된다. 애노테이션에 대한 자세한 내용은 따로 설명한다.

이 애노테이션은 상위 클래스의 메서드를 오버라이드하는 것임을 나태낸다.
이름 그대로 오버라이딩한 메서드 위에 이 애노테이션을 붙여야 한다.
컴파일러는 이 애노테이션을 보고 메서드가 정확히 오버라이드 되었는지 확인한다. 오버라이딩 조건을 만족시키지 않으면 컴파일 에러를 발생시킨다. 따라서 실수로 오버라이딘을 못하는 경우를 방지해준다. 예를 들어서 이 경우에 만약 부모에 move() 메서드가 없다면 컴파일 오류가 발생한다. 참고로 이 기능은 필수는 아니지만 코드의 명확성을 위해 붙여주는 것이 좋다.

 

 

메서드 오버라이딩 조건

메서드 오버라이딩은 다음과 같은 까다로운 조건을 가지고 있다.

다음 내용은 아직 학습하지 않은 내용들도 있으므로 모두 이해하려고 하기 보다는 참고만 한다.

지금은 단순히 부모 메서드와 같은 메서드를 오버라이딩 할 수 있다. 정도로 이해하면 충분하다.

 

메서드 오버라이딩 조건

  • 메서드 이름: 메서드 이름이 같아야 한다.
  • 메서드 파라미터: 파라미터 타입, 순서, 개수가 같아야 한다.
  • 반환 타입: 반환 타입이 같아야 한다. 단 반환 타입이 하위 클래스 타입일 수 있다.
  • 접근 제어자: 오버라이딩 메서드의 접근 제어자는 상위 클래스의 메서드보다 더 제한적이어서는 안된다. 예를 들어, 상위 클래스의 메서드가 protected 로 선언되어 있으면 하위 클래스에서 이를 public 또는 protected 로 오버라이드할 수 있지만, private 또는 default 로 오버라이드 할 수 없다.
  • 예외: 오버라이딩 메서드는 상위 클래스의 메서드보다 더 많은 체크 예외를 throws 로 선언할 수 없다. 하지만 더 적거나 같은 수의 예외, 또는 하위 타입의 예외는 선언할 수 있다. 예외를 학습해야 이해할 수 있다. 예외는 뒤에서 다룰 것이다.
  • static, final, private: 키워드가 붙은 메서드는 오버라이딩 될 수 없다.
    • static 은 클래스 레벨에서 작동하므로 인스턴스 레벨에서 사용하는 오버라이딩이 의미가 없다. 쉽게 이야기해서 그냥 클래스 이름을 통해 필요한 곳에 직접 접근하면 된다.
    • final 메서드는 재정의를 금지한다.
    • private 메서드는 해당 클래스에서만 접근 가능하기 때문에 하위 클래스에서 보이지 않는다. 따라서 오버라이딩 할 수 없다.
  • 생성자 오버라이딩: 생성자는 오버라이딩 할 수 없다.

 

0 0
JAVA
이 공간은 개인 공부를 통해 얻은 정보를 체계적으로 정리하고 공유하는 곳입니다. 학습한 내용, 발견한 지식, 그리고 문제 해결 방법 등을 기록하여 나만의 학습 자료를 구축하고, 필요할 때 쉽게 참고할 수 있는 유용한 자원으로 활용할 수 있도록 합니다.
Yesterday: 456
Today: 231