Java Inheritance
자바 상속 (Java Inheritance): 개념 및 사용법
- *상속(Inheritance)**은 객체 지향 프로그래밍(OOP)의 중요한 개념 중 하나로, 새로운 클래스가 기존 클래스의 속성과 메서드를 물려받아 재사용할 수 있게 해주는 기능입니다. 상속을 사용하면 코드의 재사용성을 높이고, 유지보수성을 향상시키며, 코드 중복을 줄일 수 있습니다.
이 글에서는 자바에서 상속의 개념, 사용법, 장점 및 다양한 예제를 다룹니다.
상속이란?
상속은 자식 클래스가 부모 클래스의 속성과 메서드를 물려받는 것을 의미합니다. 부모 클래스의 멤버를 그대로 사용할 수 있으며, 자식 클래스에서 필요한 기능을 추가하거나 변경(오버라이딩)할 수 있습니다.
- 부모 클래스(Superclass): 상속을 제공하는 클래스. 기초 클래스 또는 기본 클래스라고도 합니다.
- 자식 클래스(Subclass): 부모 클래스의 속성과 메서드를 물려받는 클래스. 파생 클래스 또는 하위 클래스라고도 합니다.
상속의 문법
자바에서 상속은 extends
키워드를 사용하여 선언됩니다. 자식 클래스는 부모 클래스의 모든 필드와 메서드를 상속받습니다.
class 부모클래스 {
// 부모 클래스의 필드와 메서드
}
class 자식클래스 extends 부모클래스 {
// 자식 클래스의 필드와 메서드 (필요 시 부모 클래스의 기능 확장 가능)
}
상속 예제
// 부모 클래스
class Animal {
String name;
public void eat() {
System.out.println(name + " is eating.");
}
}
// 자식 클래스
class Dog extends Animal {
public void bark() {
System.out.println(name + " is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.name = "Buddy";
dog.eat(); // 상속받은 메서드 호출
dog.bark(); // 자식 클래스의 메서드 호출
}
}
결과:
Buddy is eating.
Buddy is barking.
위 예제에서 Dog
클래스는 Animal
클래스를 상속받아 name
필드와 eat()
메서드를 사용하고, 새로운
메서드 bark()
를 추가했습니다. 이를 통해 자식 클래스에서 부모 클래스의 기능을 확장할 수 있습니다.
상속의 장점
- 코드 재사용: 부모 클래스에 정의된 코드를 자식 클래스에서 재사용할 수 있어 코드 중복을 줄입니다.
- 유지보수성: 부모 클래스의 코드가 변경되면 이를 상속받는 모든 자식 클래스에 적용되므로 유지보수가 용이합니다.
- 확장성: 자식 클래스에서 부모 클래스의 기능을 확장하거나 새로운 기능을 추가할 수 있습니다.
상속의 종류
자바에서 상속은 주로 **단일 상속(Single Inheritance)**을 지원하며, **다중 상속(Multiple Inheritance)**은 허용되지 않습니다. 그러나 자바는 인터페이스를 통해 다중 상속과 비슷한 효과를 낼 수 있습니다.
1. 단일 상속 (Single Inheritance)
자바에서는 하나의 클래스만 상속받을 수 있습니다. 즉, 한 자식 클래스가 여러 부모 클래스를 상속받는 것은 불가능합니다. 하지만 자식 클래스는 인터페이스를 다중으로 구현할 수 있습니다.
class Parent {
// 부모 클래스
}
class Child extends Parent {
// 자식 클래스
}
2. 다중 상속 불가 (Multiple Inheritance)
자바는 다중 상속을 허용하지 않습니다. 다중 상속이란 한 클래스가 두 개 이상의 부모 클래스로부터 상속받는 것을 의미합니다. 이는 상속받은 메서드나 필드 간의 충돌 문제를 일으킬 수 있어 자바에서는 이를 방지하기 위해 다중 상속을 금지하고 있습니다.
// 다중 상속은 불가능
class Child extends Parent1, Parent2 { // 오류 발생
// 자바에서는 다중 상속 불가
}
3. 인터페이스를 통한 다중 상속
자바에서 인터페이스를 사용하면 다중 상속과 유사한 효과를 얻을 수 있습니다. 클래스는 여러 인터페이스를 구현할 수 있으며, 인터페이스는 메서드의 구현을 포함하지 않기 때문에 충돌 없이 다중 상속의 효과를 냅니다.
interface Flyable {
void fly();
}
interface Swimmable {
void swim();
}
class Duck implements Flyable, Swimmable {
public void fly() {
System.out.println("The duck is flying.");
}
public void swim() {
System.out.println("The duck is swimming.");
}
}
메서드 오버라이딩 (Method Overriding)
- *메서드 오버라이딩(Method Overriding)**은 자식 클래스에서 부모 클래스의 메서드를 재정의하는 것입니다. 부모 클래스의 메서드와 동일한 이름, 매개변수, 반환 타입을 사용해야 하며, 부모 클래스에서 제공하는 기본 동작을 자식 클래스에 맞게 변경할 수 있습니다.
메서드 오버라이딩 예제
class Animal {
public void sound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Animal animal = new Animal();
animal.sound(); // 출력: Some generic animal sound
Dog dog = new Dog();
dog.sound(); // 출력: Bark (오버라이딩된 메서드)
}
}
결과:
Some generic animal sound
Bark
위 예제에서 Dog
클래스는 Animal
클래스의 sound()
메서드를 오버라이딩하여 자신만의 방식으로 메서드를 구현했습니다.
@Override
어노테이션을 사용하여 메서드가 정확히 오버라이딩된 것인지 컴파일러가 확인할 수 있도록 합니다.
super
키워드
super
키워드는 부모 클래스의 메서드나 생성자를 호출할 때 사용됩니다. 자식 클래스에서 부모 클래스의 메서드를 호출하거나, 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출할 때
유용합니다.
super
를 사용한 부모 클래스 메서드 호출
class Animal {
public void sound() {
System.out.println("Some generic animal sound");
}
}
class Dog extends Animal {
@Override
public void sound() {
super.sound(); // 부모 클래스의 sound() 메서드 호출
System.out.println("Bark");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.sound(); // 출력: Some generic animal sound \\\\n Bark
}
}
결과:
Some generic animal sound
Bark
위 예제에서 super.sound()
는 부모 클래스 Animal
의 sound()
메서드를 호출한 후, Dog
클래스에서 재정의된 sound()
메서드가 실행됩니다.
super
를 사용한 부모 클래스 생성자 호출
자식 클래스의 생성자에서 부모 클래스의 생성자를 호출할 때 super()
를 사용합니다. super()
는 반드시 자식 클래스 생성자의 첫 줄에 위치해야 합니다.
class Animal {
String name;
// 부모 클래스 생성자
public Animal(String name) {
this.name = name;
}
}
class Dog extends Animal {
// 자식 클래스 생성자
public Dog(String name) {
super(name); // 부모 클래스의 생성자 호출
}
public void display() {
System.out.println("Dog's name is " + name);
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog("Buddy");
dog.display(); // 출력: Dog's name is Buddy
}
}
결과:
Dog's name is Buddy
위 예제에서 Dog
클래스의 생성자는 super(name)
을 통해 부모 클래스 Animal
의 생성자를 호출하여 이름을 초기화합니다.
상속에서의 접근 제어
상속에서의 접근 제어는 자식 클래스가 부모 클래스의 멤버에 접근할 수 있는지를 결정합니다. 자바는 접근 제어자에 따라 상속된 멤버에 대한 접근 권한을 제어합니다.
public
: 어디서든 접근 가능. 자식 클래스에서도 접근할 수 있습니다.protected
: 같은 패키지나 상속받은 자식 클래스에서 접근 가능.default
(접근 제어자를 명시하지 않은 경우): 같은 패키지 내에서만 접근 가능.private
: 해당 클래스 내부에서만 접근 가능. 자식 클래스에서 접근할 수 없습니다.
요
약
- *상속(Inheritance)**은 부모 클래스의 속성과 메서드를 자식 클래스가 물려받아 재사용하는 기능입니다.
- 자바는 **단일 상속(Single Inheritance)**만 지원하며, 다중 상속은 허용되지 않지만 인터페이스를 통해 다중 상속과 유사한 효과를 얻을 수 있습니다.
- 메서드 오버라이딩을 통해 부모 클래스의 메서드를 자식 클래스에서 재정의할 수 있습니다.
super
키워드는 부모 클래스의 메서드나 생성자를 호출하는 데 사용됩니다.- 상속을 통해 코드 재사용성이 높아지고, 유지보수성이 향상됩니다.
자바 상속을 적절히 활용하면 더 효율적인 코드 작성을 할 수 있으며, 객체 지향 프로그래밍의 강력한 기능을 사용할 수 있습니다.