Java에서 "오버라이딩(Overriding)"은 상속 관계에서 발생하는 개념으로, 부모 클래스(상위 클래스)에서 이미 정의된 메소드를 자식 클래스(하위 클래스)에서 동일한 시그니처(메소드 이름, 매개변수 리스트, 반환 타입)로 다시 정의하는 것을 말합니다. 이를 통해 자식 클래스는 부모 클래스의 메소드를 재정의하여 자신에 맞게 동작하도록 할 수 있습니다.
오버라이딩의 조건
- 메소드 시그니처가 같아야 함: 오버라이딩을 하려면 메소드 이름, 매개변수 리스트, 반환 타입이 부모 클래스의 메소드와 정확히 일치해야 합니다.
- 상속 관계에 있어야 함: 오버라이딩은 상속 관계에서만 발생합니다. 즉, 자식 클래스가 부모 클래스를 상속받은 상태여야 합니다.
- 접근 제어자 조건: 오버라이딩된 메소드는 접근 제어자를 더 강하게 변경할 수 있습니다. 예를 들어, 부모 클래스의 메소드가 public이면 자식 클래스에서 public이나 protected로 오버라이딩할 수 있지만, private이나 package-private으로는 변경할 수 없습니다.
오버라이딩의 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class Animal {
public void makeSound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("Bark bark!");
}
}
class Cat extends Animal {
@Override
public void makeSound() {
System.out.println("Meow meow!");
}
}
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.makeSound(); // 출력: Bark bark!
animal2.makeSound(); // 출력: Meow meow!
}
}
|
cs |
위 예시에서 Animal 클래스의 makeSound() 메소드는 Dog 클래스와 Cat 클래스에서 각각 오버라이딩 되었습니다. Dog 클래스의 makeSound() 메소드는 "Bark bark!"를 출력하고, Cat 클래스의 makeSound() 메소드는 "Meow meow!"를 출력합니다. 이 때, main 메소드에서 Animal 타입의 변수로 Dog와 Cat 객체를 참조하고 있지만, 오버라이딩된 메소드가 호출됩니다. 이것이 Java의 다형성(polymorphism)의 한 예시입니다.
오버라이딩 시 주의사항
- 무한 루프 주의: 오버라이딩된 메소드 내에서 부모 클래스의 메소드를 호출할 때, 자신의 메소드를 호출하는 것이 아니라 부모 클래스의 메소드를 호출해야 합니다. 그렇지 않으면 무한 루프에 빠질 수 있습니다.
- @Override 어노테이션 사용: 컴파일러에게 해당 메소드가 오버라이딩된 것임을 명시적으로 알려주기 위해 @Override 어노테이션을 사용하는 것이 좋습니다.
- 동적 바인딩: Java에서는 오버라이딩된 메소드는 실행 시점에 객체의 실제 타입에 따라 동적으로 바인딩됩니다. 따라서 메소드 호출 시 객체의 타입에 맞는 오버라이딩된 메소드가 호출됩니다.
오버라이딩을 통해 자식 클래스는 부모 클래스의 메소드를 더 적합하게 재정의하여 사용할 수 있으며, 이는 객체지향 프로그래밍의 다형성 개념을 실현하는 중요한 방법 중 하나입니다.