자바 예제에서 상속

자바에서의 상속은 객체 지향 프로그래밍의 핵심 개념 중 하나입니다. 자바 상속은 객체 간 is-a 관계가 있는 경우에 사용됩니다. 자바에서는 extends 키워드를 사용하여 상속을 구현합니다.

자바에서의 상속

자바에서의 상속은 다른 클래스로부터 상속받아 클래스 간 계층 구조를 만드는 방법입니다.

자바 상속은 추이적입니다. 즉, Sedan이 Car를 확장하고 Car가 Vehicle을 확장한다면 Sedan은 Vehicle 클래스를 상속받습니다. Vehicle은 Car와 Sedan의 슈퍼클래스가 됩니다.

상속은 자바 애플리케이션에서 널리 사용되며, 예를 들어 예외 클래스를 확장하여 에러 코드와 같은 추가 정보를 포함하는 애플리케이션별 예외 클래스를 생성하는 데 사용됩니다. 예를 들어 NullPointerException입니다.

자바 상속 예제

자바에서 모든 클래스는 암묵적으로 java.lang.Object 클래스를 확장합니다. 따라서 Object 클래스는 자바의 상속 계층 구조의 최상위에 위치합니다.

간단한 예제를 통해 자바에서 상속을 구현하는 방법을 살펴보겠습니다.

슈퍼클래스: Animal

package com.journaldev.inheritance;

public class Animal {

	private boolean vegetarian;

	private String eats;

	private int noOfLegs;

	public Animal(){}

	public Animal(boolean veg, String food, int legs){
		this.vegetarian = veg;
		this.eats = food;
		this.noOfLegs = legs;
	}

	public boolean isVegetarian() {
		return vegetarian;
	}

	public void setVegetarian(boolean vegetarian) {
		this.vegetarian = vegetarian;
	}

	public String getEats() {
		return eats;
	}

	public void setEats(String eats) {
		this.eats = eats;
	}

	public int getNoOfLegs() {
		return noOfLegs;
	}

	public void setNoOfLegs(int noOfLegs) {
		this.noOfLegs = noOfLegs;
	}

}

전체적으로 코드 재사용은 상속의 가장 중요한 이점입니다. 하위 클래스는 상위 클래스의 변수와 메서드를 상속합니다.

하위 클래스: Cat

package com.journaldev.inheritance;

public class Cat extends Animal{

	private String color;

	public Cat(boolean veg, String food, int legs) {
		super(veg, food, legs);
		this.color="White";
	}

	public Cat(boolean veg, String food, int legs, String color){
		super(veg, food, legs);
		this.color=color;
	}

	public String getColor() {
		return color;
	}

	public void setColor(String color) {
		this.color = color;
	}

}

Java에서 상속을 구현하는 데 `extends` 키워드를 사용하고 있다는 것에 주목하세요.

Java 상속 테스트 프로그램

간단한 테스트 클래스를 작성하여 Cat 객체를 만들고 해당 메서드 중 일부를 사용해 봅시다.

package com.journaldev.inheritance;

public class AnimalInheritanceTest {

	public static void main(String[] args) {
		Cat cat = new Cat(false, "milk", 4, "black");

		System.out.println("Cat is Vegetarian?" + cat.isVegetarian());
		System.out.println("Cat eats " + cat.getEats());
		System.out.println("Cat has " + cat.getNoOfLegs() + " legs.");
		System.out.println("Cat color is " + cat.getColor());
	}

}

출력:

Cat 클래스에는 `getEats()` 메서드가 없지만 여전히 프로그램이 작동합니다. 왜냐하면 이것이 Animal 클래스에서 상속되었기 때문입니다.

중요한 점

  1. 변수와 메서드를 상속받기 때문에 코드 재사용이 상속의 가장 중요한 이점입니다.

  2. 상위 클래스의 `private` 멤버는 하위 클래스에서 직접 액세스할 수 없습니다. 이 예에서 Animal 변수 `noOfLegs`는 Cat 클래스에서 직접 액세스할 수 없지만 getter 및 setter 메서드를 통해 간접적으로 액세스할 수 있습니다.

  3. 기본 액세스 권한을 가진 수퍼클래스 멤버는 동일한 패키지에 있을 경우에만 하위 클래스에서 액세스할 수 있습니다.

  4. 수퍼클래스 생성자는 하위 클래스에 상속되지 않습니다.

  5. 만약 수퍼클래스에 기본 생성자가 없다면, 하위 클래스에서도 명시적 생성자를 정의해야 합니다. 그렇지 않으면 컴파일 시간 예외가 발생합니다. 이 경우 하위 클래스 생성자에서 수퍼클래스 생성자를 호출하는 것이 필수이며, 하위 클래스 생성자의 첫 번째 문장이어야 합니다.

  6. Java는 다중 상속을 지원하지 않습니다, 하위 클래스는 하나의 클래스만 확장할 수 있습니다. Animal 클래스는 암시적으로 Object 클래스를 확장하고 Cat은 Animal 클래스를 확장하지만 자바 상속의 추이적 특성으로 인해 Cat 클래스도 Object 클래스를 확장합니다.

  7. 우리는 하위 클래스의 인스턴스를 만들고 이를 수퍼클래스 변수에 할당할 수 있습니다. 이를 업캐스팅이라고 합니다. 아래는 업캐스팅의 간단한 예입니다:

    Cat c = new Cat(); // 하위 클래스의 인스턴스
    Animal a = c; // 업캐스팅, Cat도 Animal이므로 괜찮습니다
    
  8. 슈퍼클래스의 인스턴스가 서브클래스 변수에 할당되면 다운캐스팅이라고 합니다. 명시적으로 이를 서브클래스로 캐스팅해야 합니다. 예를 들면;

    Cat c = new Cat();
    Animal a = c;
    Cat c1 = (Cat) a; //명시적 캐스팅, "c"가 실제로 Cat 유형이기 때문에 잘 작동합니다
    

    컴파일러는 명시적 캐스팅 덕분에 잘못된 작업을 하더라도 에러를 표시하지 않습니다. 아래는 런타임에서 ClassCastException이 발생하는 몇 가지 경우입니다.

    Dog d = new Dog();
    Animal a = d;
    Cat c1 = (Cat) a; //런타임에서 ClassCastException 발생
    
    Animal a1 = new Animal();
    Cat c2 = (Cat) a1; //런타임에서 a1이 실제로 Animal 유형이기 때문에 ClassCastException 발생
    
  9. 우리는 슈퍼클래스의 메소드를 서브클래스에서 오버라이드할 수 있습니다. 그러나 항상 오버라이드된 메소드에는 @Override 어노테이션을 붙여야 합니다. 컴파일러는 우리가 메소드를 오버라이드하고 있음을 알 수 있으며, 슈퍼클래스 메소드에 변경이 있으면 런타임에서 원하지 않는 결과가 아닌 컴파일 타임 에러가 발생합니다.

  10. 우리는 super 키워드를 사용하여 슈퍼클래스 메소드를 호출하고 슈퍼클래스 변수에 접근할 수 있습니다. 이것은 하위 클래스에 같은 이름의 변수/메소드가 있지만 슈퍼클래스 변수/메소드에 접근하고 싶을 때 유용합니다. 또한 슈퍼클래스와 하위 클래스에 생성자가 정의되어 있고 슈퍼클래스 생성자를 명시적으로 호출해야 할 때도 사용됩니다.

  11. instanceof 명령문을 사용하여 객체 간의 상속을 확인할 수 있습니다. 아래 예제를 통해 살펴보겠습니다.

```
Cat c = new Cat();
Dog d = new Dog();
Animal an = c;

boolean flag = c instanceof Cat; //normal case, returns true

flag = c instanceof Animal; // returns true since c is-an Animal too

flag = an instanceof Cat; //returns true because a is of type Cat at runtime

flag = an instanceof Dog; //returns false for obvious reasons.
```
  1. 자바에서는 Final 클래스를 확장할 수 없습니다.
  2. 만약 코드에서 슈퍼클래스를 사용하지 않을 거라면 즉, 슈퍼클래스가 재사용 가능한 코드를 유지하기 위한 기본이라면 클라이언트 클래스에 의한 불필요한 인스턴스화를 피하기 위해 추상 클래스로 유지할 수 있습니다. 또한 기본 클래스의 인스턴스 생성을 제한할 것입니다.

Java 상속 비디오 튜토리얼

I have recently published two videos on YouTube explaining Inheritance in detail with sample programs, you should watch them below.


더 많은 상속 예제는 저희 GitHub 저장소에서 확인할 수 있습니다.

참고: 오라클 문서

Source:
https://www.digitalocean.com/community/tutorials/inheritance-java-example