본문 바로가기
Programming Language 👅

[Java] 상속과 오버라이딩(inheritance & overriding)

by 서니서닝 2023. 2. 28.
728x90

👩‍👦 상속(inheritance)

기존 클래스를 재사용하여 새로운 클래스를 정의하는 것

자식(하위, 파생) 클래스가 부모(상위) 클래스의 멤버를 물려받는 것

Class Vehicle {

    public int speed;
    
    public int getSpeed() {
        return speed;
    }
    public void setSpeed(int speed) {
        this.speed = speed;
    }
    
}

class Car extends Vehicle {

}

public class Test {

    public static void main(String[] args) {

        Car A = new Car();
        A.getSpeed();
    }
}

 

  • 상속 대상 : 부모의 필드와 메소드
  • 상속 효과 :
    • 부모 클래스를 재사용하여 자식 클래스를 빠르게 개발 할 수 있다.
    • 코드의 중복을 줄일 수 있다.
    • 프로그램의 생산성과 유지보수성에 크게 기여한다.
    • 객체 다형성 구현이 가능하다.
  • 생성자와 초기화 블록은 상속되지 않으며 멤버만 상속된다
  • 자손 클래스 멤버 개수는 조상 클래스보다 항상 같거나 많다
  • 자손 클래스의 인스턴스를 생성하면 조상 클래스의 멤버와 자손 클래스의 멤버가 합쳐진 하나의 인스턴스로 생성된다.
조상 클래스 부모(parent) 클래스, 상위(super) 클래스, 기반(base) 클래스
자손 클래스  자식(child) 클래스, 하위(sub) 클래스, 파생된(derived) 클래스

 

[ 포함 관계 ]

상속이 아닌 클래스 내부에 새로운 클래스를 선언하는 것

class A {
	int a;
}
class B {
	A test = new A();
	int b;
}

상속과의 차이

  • 상속 : (is - a) B는 A이다.
  • 포함 : (has - a) B는 A를 가지고 있다.

 

[ 단일 상속 ]

서브클래스가 하나의 슈퍼클래스만 가질 수 있다.

 

  • C++에선 다중 상속을 허용하지만, 자바에서는 오직 단일 상속만을 허용한다.
  • 이럴 때에 포함관계를 사용할 수 있다. (상속을 받으면서 포함관계를 하면 두 개의 클래스로부터 사용가능)
  • 부모 클래스는 여러 서브 클래스를 가질 수 있음
    • ex) Object 클래스
Object 클래스

모든 클래스의 슈퍼 클래스
모든 클래스들은 자동적으로 Object 클래스로부터 상속받게 한다.

 

 


📝 오버라이딩(overriding)

슈퍼 클래스로부터 상속받은 메소드의 내용을 재정의하는 것

상속받은 메서드를 그대로 사용하기도 하지만, 자손 클래스에 맞추어 변경이 필요할 때도 있다. 이러할 때에 조상의 메서드를 오버라이딩이라고 한다.

class Food {
    
    private int kcal;
    private int price;
    private int kg;
    
    public Food(int kcal, int price, int kg) {
        this.kcal = kcal;
        this.price = price;
        this.kg = kg;
    }

    @Override
    public String toString() {
        return "Food [kcal=" + kcal + ", price=" + price + ", kg=" + kg + "]";
    }
    
}

class Melon extends Food { //상속

    private String where;
    
    public Melon(int kcal, int price, int kg, String where) {
        super(kcal, price, kg);
        // TODO Auto-generated constructor stub
        this.where = where;
    }

    @Override
    public String toString() {
        return super.toString() + " Melon [where=" + where + "]";
    }
    
}

public class whatFood {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Melon mel = new Melon(100, 4000, 3, "Afganistan");
        System.out.println(mel.toString());
    }

}

 

[ 오버라이딩 조건 ]

  • 슈퍼 클래스와 이름(메소드 명), 매개변수, 반환타입이 같아야한다.
  • 접근제어자는 조상클래스의 메서드보다 좁은 범위로 변경할 수 있다.
    • ex ) 조상 클래스의 정의된 메서드의 접근 제어자가 protected
    • 이를 오버라이딩하는 자손 클래스의 메서드는 접근 제어자가 protected 또는 public이어야 한다.
    • (대부분은 같은 번위의 접근 제어자 사용)
  • 슈퍼 클래스의 메서드보다 많은 수의 예외를 선언할 수 없다.
    • 예외의 수 뿐 아니라 범위 또한 고려해야 한다.
  • 인스턴스 메소드를 static 메소드 또는 그 반대로 변경할 수 없다.
  • @Override 어노테이션을 사용하면 좋다.
  • 오버라이딩이 불가능한 경우
    • private 메소드 : 부모 클래스 전용이므로 자식 클래스에 상속되지 않음
    • 정적 메소드 : 클래스 소속이므로 자식 클래스에 상속되지 않음
    • final 메소드 : 더이상 수정할 수 없으므로 오버라이딩 불가
class A {
	void f() throws IOException, SQLException{}
}

//올바른 사용
class B extends A{
	void f() throws IOException {}
}

//error
class C extends A{
	void f() throws Exception{}
}

/* Exception은 모든 예외의 조상임, 단순히 예외의 수가 아닌 범위(상속관계) 또한 고려해야함

 

[ 오버로딩 vs 오버라이딩 ]

오버로딩(overloading)은 기존에 없는 새로운 메서드를 추가하는 것(new)

오버라이딩(overriding)은 조상으로부터 상속받은 메서드의 내용을 변경하는 것(change, modify)

 

[ super ]

서브 클래스에서 슈퍼 클래스로부터 상속받은 멤버를 참조하는 데 사용되는 참조변수

class A {
	int a;
	int b;
}
class B extends A {
	int b;
	//모두 슈퍼클래스의 a를 참조
	a;
	this.a;
	super.a;
	//서브 클래스의 b를 참조
	b;
	this.b;
	//super 클래스의 b를 참조
	super.b;
}
  • 멤버변수와 지역변수의 이름이 같을 때 this를 붙여서 구별하듯이 상속받은 멤버와 자신의 멤버가 이름이 같을 때 super를 붙여 구분할 수 있다.
    • super.a, super.method()
  • 조상클래스로부터 상속받은 멤버도 클래스 자신의 멤버이므로 super대신 this를 사용할 수 있다.
  • 조상클래스의 멤버와 자손 클래스의 멤버가 중복 정의되어서 서로 구별해야 하는 경우에만 super를 사용하는 것이 좋다.
  • super역시 인스턴스가 있어야하므로 static 변수나 메소드에는 접근 불가

 

[ super() 메소드 ]

슈퍼 클래스의 생성자 호출

this()는 같은 클래스의 다른 생성자를 호출하지만 super()는 조상클래스의 생성자를 호출하는 데 사용된다.

 

  • Object Class를 제외한 모든 생성자의 첫 줄에는 this() 또는 super()를 삽입해야한다.
    • 그렇지 않으면 컴파일러가 자동으로 super() 삽입
    • 명시적 상속관계가 없다면 super()를 통해 Object() 삽입
    • 서브클래스의 생성자에 super(args) 를 삽입하지 않으면 자동으로 super()를 삽입한다. 이때 슈퍼클래스에 기본 생성자가 없다면 컴파일 에러 발생

  • 생성자의 첫 줄에서 조상클래스의 생성자를 호출해야 하는 이유
    • 자손클래스의 멤버가 조상클래스의 멤버를 사용할 수도 있으므로 조상의 멤버들이 먼저 초기화되어 있어야 한다.
    • 조상클래스에서 초기화 한 값을 쓰기 위해서는 조상에서 먼저 초기화 작업을 해야한다.
    • 부모의 생성자가 먼저 초기화 되어 있어야 자식도 생성자를 생성할 수 있다.
    • 처음에 아무것도 안 쓰면 자식은 부모의 기본 생성자로 초기화할 수 있다.

  • 자손 클래스의 인스턴스를 생성하면, 자손의 멤버와 조상의 멤버가 합쳐진 하나의 인스턴스가 생성된다.
    • 이때 조상클래스의 멤버의 초기화 작업이 수행되어야 하기 때문에 자손클래스의 생성자에게 조상클래스의 생성자가 호출되어야 한다.
  • super()로 기본 생성자 아닌 부모에서 작성한 다른 생성자로 초기화 할 수 있다.

 

📖 참고 자료

[Java] 상속 - 메소드 오버로딩과 오버라이딩의 차이, 패키지, super(), 클래스 상속 extends

Java 12 : 상속(extends)과 오버라이딩(Override)

[JAVA] 상속과 오버라이딩

728x90

'Programming Language 👅' 카테고리의 다른 글

[Java] 자바는 Call by Value!  (0) 2023.05.19
[Java] 제네릭(Generic)  (0) 2023.04.25
[Java] Stream API  (0) 2023.04.10
[Java] 자바의 컴파일 과정  (0) 2023.03.27

댓글