상속이란?
한 클래스가 다른 클래스의 속성과 메서드를 물려받는 것
중복되는 속성과 메서드를 복사하여 코드의 재사용성을 높이고 유지 보수를 쉽게 함
extends 키워드를 사용 (예시 : class 자식클래스명 extends 부모클래스명)
instanceof 연산자로 상속 관계 확인 가능 (예시 : if(자식클래스명 instanceof 부모클래스명))
- 상속하는 부모 클래스 = Super Class (Base Class) : 기존 속성과 메서드를 정의한 클래스
- 상속받는 자식 클래스 = Sub Class (Derived Class) : 기존 속성과 메서드를 확장하여 새로운 기능을 추가하는 클래스
상속의 특징
- is-a 관계임
- Sub Class에서 Super Class에 없는 메서드나 인스턴스 변수를 추가할 수 있음
- Sub Class에서 Super Class의 속성과 메서드를 사용, 변경, 확장하여 사용할 수 있음
- Sub Class에서 Super Class의 Private, Static, Final 메서드 또는 변수에 대해서는 접근 불가할 수 있음
- 특히, Final class는 상속이 불가능하고 Final method는 오버라이딩이 불가능함
- Super Class의 참조가 Sub Class가 되는 경우는 안전하지 않을 수 있음 (ILLEGAL)
- Java에서 클래스의 다중 상속은 불가능하지만, 인터페이스(Interfaces)의 다중 상속은 가능함
- Java의 많은 메서드들은 Object class에서 상속 받은 것임
// Super Class
class Animal {
String name;
void eat() {
System.out.println(name + " is eating food.");
}
}
// Sub Class (Animal 클래스를 상속)
class Dog extends Animal { // extends로 상속
void bark() {
System.out.println(name + " is barking.");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog();
myDog.name = "Poppi"; // Super Class의 필드 사용
myDog.eat(); // Super Class의 메서드 사용
myDog.bark(); // Sub Class의 메서드 사용
}
}
매서드 오버라이딩 / Method Overriding
부모 클래스의 메서드를 자식 클래스에서 재정의하여 다르게 동작하게 할 수 있음
@Override 어노테이션을 사용하여 오버라이딩을 명확히 표시
※ 오버로딩(Overloading)과는 다르다 (여기를 참조)
class Animal {
void makeSound() {
System.out.println("Animal makes sounds.");
}
}
class Dog extends Animal {
@Override // 어노테이션으로 명시
void makeSound() { // 부모 클래스의 메서드를 재정의
System.out.println("Bow-wow!");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Animal();
myAnimal.makeSound(); // "Animals make sounds."
Dog myDog = new Dog();
myDog.makeSound(); // "Bow-wow!" (오버라이딩된 메서드 실행)
}
}
업캐스팅 & 다운캐스팅 (Upcasting & Downcasting)
상속 관계에서 객체 간 타입 변환이 가능함
- 업캐스팅 (Upcasting)
- 자식 클래스 → 부모 클래스
- 컴파일러에서 자동으로 변환
- 부모 클래스 타입의 참조 변수로 자식 클래스의 객체를 참조
- 자식 클래스의 메서드를 부모 클래스 타입으로 호출 가능
- 하지만, 자식 클래스에만 있는 멤버(필드, 메서드)에는 접근 불가능
- 오버라이딩된 메서드는 자식 클래스의 메서드를 따름
- 다운캐스팅 (Downcasting)
- 부모 클래스 → 자식 클래스
- 부모 타입을 다시 자식 타입으로 변환
- 명시적 변환 필요 (자식 클래스명 괄호)
- 부모 클래스에서 선언되지 않은 자식의 멤버(필드, 메서드)에 접근 가능
- 잘못된 다운캐스팅은 ClassCastException 발생 가능
- instanceof 연산자를 사용하여 변환이 안전한지 확인
class Animal {
void makeSound() {
System.out.println("Animal makes sounds.");
}
}
class Dog extends Animal {
@Override
void makeSound() {
System.out.println("Bow-wow!");
}
void wagTail() {
System.out.println("Wagging the tail.");
}
}
public class Main {
public static void main(String[] args) {
Animal myAnimal = new Dog(); // 업캐스팅
myAnimal.makeSound(); // 출력 : Bow-wow!, 오버라이딩된 메서드 호출
if (myAnimal instanceof Dog) { // instanceof로 변환 안전 확인
Dog myDog = (Dog) myAnimal; // 다운캐스팅 (명시적)
myDog.wagTail(); // 출력 : Wagging the tail.
}
}
}
super, super()
- super : 부모 클래스의 필드나 메서드를 호출할 때 사용
- 부모의 메서드를 자식 클래스에서 오버라이딩 후 호출 가능 (예시 : super.메서드())
- super() : 자식 클래스에서 부모의 생성자를 호출할 때 사용
- 생성자는 기본적으로 상속되지 않으나, Sub Class의 생성자 안에 super(); 를 사용하여 가져올 수 있음
- Sub Class에서는 반드시 super(); 를 이용한 생성자를 만들어야 하며, 생성하지 않으면 default 생성자가 생성됨
class Animal {
String name;
Animal(String name) {
this.name = name;
}
void makeSound() {
System.out.println(name + " makes sounds.");
}
}
class Dog extends Animal {
Dog(String name) {
super(name); // super()로 부모 클래스의 생성자 호출
}
@Override
void makeSound() {
super.makeSound(); // super로 부모 클래스의 메서드 호출
System.out.println("Bow-wow!");
}
}
public class Main {
public static void main(String[] args) {
Dog myDog = new Dog("Poppi");
myDog.makeSound();
}
}
'Programming > Java' 카테고리의 다른 글
[Java] is-a 관계와 has-a 관계 (0) | 2025.03.04 |
---|---|
[Java] 생성자 (Constructor) (0) | 2025.03.04 |
[Java] 클래스 변수, 인스턴스 변수, 로컬 변수, 매개 변수 (0) | 2025.02.28 |
[Java] Java란? (1) | 2025.02.28 |