본문 바로가기

언어 기초/JAVA

상속 [JAVA | 학습을 위한 자료 | 김영한 자바 기본]

상속은 객체 지향 프로그래밍의 핵심 요소 중 하나로, 기존 클래스의 필드와 메서드를 새로운 클래스에서 재사용하게 해준다. 이름 그대로 기존 클래스의 속성과 기능을 그대로 물려받는 것이다. 상속을 사용하려면 extends 키워드를 사용하면 된다. 그리고 extends 대상은 하나만 선택할 수 있다.

용어 정리

  • 부모 클래스 (슈퍼 클래스): 상속을 통해 자신의 필드와 메서드를 다른 클래스에 제공하는 클래스
  • 자식 클래스 (서브 클래스): 부모 클래스로부터 필드와 메서드를 상속받는 클래스

상속은 부모의 기능을 자식이 물려 받는 것이다. 따라서 자식이 부모의 기능을 물려 받아서 사용할 수 있다. 반대로 부모 클래스는 자식 클래스에 접근할 수 없다. 자식 클래스는 부모 클래스의 기능을 물려 받기 때문에 접근할 수 있지만 그 반대는 아니다. 부모 코드를 보자! 자식에 대한 정보가 하나도 없다.

상속과 메모리구조

상속이라고 해서 단순하게 부모의 필드와 메서드만 물려 받는게 아니다. 상속 관계를 사용하면 부모 클래스도 함께 포함 해서 생성된다. 외부에서 볼때는 하나의 인스턴스를 생성하는 것 같지만 내부에서는 부모와 자식이 모두 생성되고 공간도 구분된다.

부모에서도 해당 기능을 찾지 못하면 더 상위 부모에서 필요한 기능을 찾아본다. 부모에 부모로 계속 올라가면서 필드나 메서드를 찾는 것이다. 물론 계속 찾아도 없으면 컴파일 오류가 발생한다.

  • 상속 관계의 객체를 생성하면 그 내부에는 부모와 자식이 모두 생성된다.
  • 상속 관계의 객체를 호출할 때, 대상 타입을 정해야 한다. 이때 호출자의 타입을 통해 대상 타입을 찾는다.
  • 현재 타입에서 기능을 찾지 못하면 상위 부모 타입으로 기능을 찾아서 실행한다. 기능을 찾지 못하면 컴파일 오류가 발생한다.

상속과 메서드 오버라이딩

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

@Override

이 애노테이션은 상위 클래스의 메서드를 오버라이드하는 것임을 나타낸다.

@Override는 자바에서 사용하는 어노테이션으로, 메서드가 부모 클래스에서 상속받은 메서드를 재정의할 때 사용된다. 이 어노테이션을 사용하면 컴파일러에게 해당 메서드가 상위 클래스에 있는 메서드를 재정의(override)한 것임을 명확히 알릴 수 있다. 이를 통해 컴파일 시점에 실수를 방지할 수 있다.

오버라이딩 조건을 만족시키지 않으 면 컴파일 에러를 발생시킨다. 따라서 실수로 오버라이딩을 못하는 경우를 방지해준다.

오버로딩(Overloading)과 오버라이딩(Overriding)

메서드 오버로딩: 메서드 이름이 같고 매개변수(파라미터)가 다른 메서드를 여러개 정의하는 것을 메서드 오버로딩(Overloading)이라 한다. 오버로딩은 번역하면 과적인데, 과하게 물건을 담았다는 뜻이다. 따라서 같은 이름 의 메서드를 여러개 정의했다고 이해하면 된다. 메서드 오버라이딩: 메서드 오버라이딩은 하위 클래스에서 상위 클래스의 메서드를 재정의하는 과정을 의미한다. 따라서 상속 관계에서 사용한다. 부모의 기능을 자식이 다시 정의하는 것이다. 오버라이딩을 단순히 해석하면 무 언가를 넘어서 타는 것을 말한다. 자식의 새로운 기능이 부모의 기존 기능을 넘어 타서 기존 기능을 새로운 기능으 로 덮어버린다고 이해하면 된다. 오버라이딩을 우리말로 번역하면 무언가를 다시 정의한다고 해서 재정의라 한다. 상속 관계에서는 기존 기능을 다시 정의한다고 이해하면 된다. 실무에서는 메서드 오버라이딩, 메서드 재정의 둘 다 사용한다.

메서드 오버라이딩 조건

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

super - 부모 참조

부모와 자식의 필드명이 같거나 메서드가 오버라이딩 되어 있으면, 자식에서 부모의 필드나 메서드를 호출할 수 없다. super 키워드를 사용하면 부모를 참조할 수 있다. super는 이름 그대로 부모 클래스에 대한 참조를 나타낸다.

super - 생성자

상속 관계의 인스턴스를 생성하면 결국 메모리 내부에는 자식과 부모 클래스가 각각 다 만들어진다. Child 를 만들면 부모인 Parent까지 함께 만들어지는 것이다. 따라서 각각의 생성자도 모두 호출되어야 한다.

상속 관계를 사용하면 자식 클래스의 생성자에서 부모 클래스의 생성자를 반드시 호출해야 한다.(규칙)

상속 관계에서 부모의 생성자를 호출할 때는 super(...) 를 사용하면 된다.

문제와 풀이

문제: 상속 관계 상품

  • 쇼핑몰의 판매 상품을 만들어보자. Book , Album , Movie 이렇게 3가지 상품을 클래스로 만들어야 한다.
  • 코드 중복이 없게 상속 관계를 사용하자. 부모 클래스는 Item 이라는 이름을 사용하면 된다.
  • 공통 속성: name , price Book: 저자(author), isbn(isbn ) Album : 아티스트( artist ) Movie: 감독(director), 배우(actor` )
public class ShopMain {
	public static void main(String[] args) {
		Book book = new Book("JAVA", 10000, "han", "12345"); 
		Album album = new Album("앨범1", 15000,"seo");
		Movie movie = new Movie("영화1", 18000,"감독1", "배우1");
         
    book.print();
    album.print();
    movie.print();
         
    int sum = book.getPrice() + album.getPrice() + movie.getPrice();
		System.out.println("상품 가격의 합: " + sum);
	}
}

실행결과

이름:JAVA, 가격:10000

  • 저자:han, isbn:12345 이름:앨범1, 가격:15000
  • 아티스트:seo 이름:영화1, 가격:18000
  • 감독:감독1, 배우:배우1 상품 가격의 합: 43000