맨위로가기

메소드 오버라이딩

"오늘의AI위키"는 AI 기술로 일관성 있고 체계적인 최신 지식을 제공하는 혁신 플랫폼입니다.
"오늘의AI위키"의 AI를 통해 더욱 풍부하고 폭넓은 지식 경험을 누리세요.

1. 개요

메소드 오버라이딩은 객체 지향 프로그래밍에서 하위 클래스가 상위 클래스의 메서드를 재정의하여, 상속받은 메서드의 동작을 변경하는 것을 의미한다. Java, C++, C#, Python, Ruby, 델파이, Ada, Eiffel, Kotlin 등 다양한 프로그래밍 언어에서 지원되며, 각 언어별로 오버라이딩을 위한 문법과 특징이 다르다. Java는 `@Override` 어노테이션을 통해 오버라이딩을 명시하고, C#은 `virtual` 및 `override` 키워드를 사용하며, Python은 동일한 이름의 메서드를 정의하여 오버라이딩한다. 오버라이딩 시에는 슈퍼클래스와 서브클래스 간의 호환성 문제를 주의해야 하며, C#과 Kotlin, Swift와 같은 언어에서는 `override` 지정을 필수로 하여 이러한 문제를 방지한다.

더 읽어볼만한 페이지

  • 메소드 (컴퓨터 프로그래밍) - 소멸자 (컴퓨터 프로그래밍)
    소멸자는 객체가 메모리에서 제거되기 직전에 호출되는 멤버 함수로, 객체 자원 해제 및 정리 작업을 수행하며, C++ 등 여러 언어에서 구현되고 메모리 누수 방지에 기여한다.
  • 메소드 (컴퓨터 프로그래밍) - 동적 디스패치
    동적 디스패치는 프로그램 실행 시 호출할 메서드를 결정하는 메커니즘으로, 단일 또는 다중 객체 기준으로 선택하며, 유연성과 확장성을 높이지만 성능 오버헤드를 발생시킬 수 있다.
메소드 오버라이딩
개요
정의메소드 오버라이딩(Method Overriding)은 객체 지향 프로그래밍에서 상위 클래스(부모 클래스)로부터 상속받은 메소드를 하위 클래스(자식 클래스)에서 재정의하는 것을 의미함. 이를 통해 하위 클래스는 상위 클래스의 메소드 동작을 자신에게 맞게 변경하거나 확장할 수 있음.
목적상속받은 메소드의 기능을 하위 클래스에서 변경하거나 확장
관련 개념상속
다형성
동적 디스패치
주의 사항오버로딩(Overloading)과 혼동하지 않도록 주의
상위 클래스에서 `final`로 선언된 메소드는 오버라이딩할 수 없음
동작 방식
메소드 시그니처메소드 이름, 매개변수 목록, 반환 타입이 상위 클래스와 동일해야 함.
접근 제어자는 같거나 더 넓은 범위로 변경 가능 (예: `protected` -> `public`)
예외(Exception)는 같거나 더 구체적인 예외를 던질 수 있음.
런타임 동작런타임 시 실제 객체의 타입에 따라 호출될 메소드가 결정됨 (동적 디스패치).
상위 클래스 타입의 변수로 하위 클래스 객체를 참조할 때 오버라이딩된 메소드가 호출됨.
사용 예시
일반적인 예`Animal` 클래스의 `makeSound()` 메소드를 `Dog` 클래스에서 오버라이딩하여 "멍멍" 소리를 내도록 구현
`Shape` 클래스의 `calculateArea()` 메소드를 `Circle` 클래스에서 오버라이딩하여 원의 면적을 계산하도록 구현
활용 분야GUI 프레임워크에서 이벤트 처리
API의 확장 및 커스터마이징
알고리즘의 특정 단계를 하위 클래스에서 구현하도록 설계 (Template Method 패턴)
장점
코드 재사용성상위 클래스의 기능을 상속받아 재사용하고, 필요한 부분만 변경하여 코드 중복을 줄임.
유연성프로그램의 동작을 런타임에 동적으로 변경 가능.
확장성새로운 기능을 쉽게 추가하고 기존 기능을 수정할 수 있음.
단점
복잡성 증가상속 관계가 깊어질수록 코드의 이해도가 낮아질 수 있음.
유지보수 어려움상위 클래스의 변경이 하위 클래스에 영향을 줄 수 있음.
구현 방법 (예시, Java)
어노테이션`@Override` 어노테이션을 사용하여 컴파일러에게 오버라이딩 의도를 명확히 알림 (선택 사항).
super 키워드`super` 키워드를 사용하여 상위 클래스의 메소드를 호출할 수 있음.
프로그래밍 언어별 지원
지원 언어Java
C++
C#
Python
PHP
JavaScript (프로토타입 기반 상속)
같이 보기
관련 주제상속
다형성
객체 지향 프로그래밍
가상 함수

2. 언어별 오버라이딩

Java의 인스턴스 메서드는 가상 메서드이므로 파생 클래스에서 오버라이드할 수 있다. 인스턴스 메서드를 비가상으로 만들 방법은 없지만, `final` 키워드를 지정하여 오버라이드를 금지할 수 있다.

Java SE 5부터 도입된 애너테이션를 사용하면 메서드가 오버라이드되었음을 컴파일러에게 알릴 수 있다(올바르게 오버라이드되지 않은 경우 컴파일 오류가 발생한다). 그러나 애너테이션 지정은 선택 사항이며 필수 사항은 아니다.

C#의 오버라이딩 특징은 다음과 같다.


  • 가상 메서드 및 추상 메서드를 오버라이딩할 때는 `override` 키워드를 지정해야 한다.

: 단, 인터페이스의 메서드를 구현하는 경우에는 `override`를 지정할 필요가 없다 (불가).

  • 메서드는 기본적으로 비가상이며, `virtual`을 지정하면 오버라이딩 가능한 가상 메서드가 된다.
  • 프로퍼티, 인덱서, 이벤트도, `virtual`로 한정된 경우에는 메서드와 마찬가지로 오버라이딩 대상이 된다.
  • `sealed` 키워드를 지정하면 오버라이딩을 금지할 수 있다.


== C++ ==

C++에서는 부모 클래스의 메서드를 명시적으로 호출하기 위해 범위 지정 연산자(::)를 사용한다.[15] 예를 들어, 기본 클래스 `TRectangle`과 유도 클래스 `TBox`가 있을 때, `TBox`는 `TRectangle` 클래스의 `print()` 메서드를 오버라이드하며, 자신의 높이를 추가로 출력한다.[15] 이때 `TBox`의 `print()` 메서드 내에서 `TRectangle::print()`를 호출하여 부모 클래스의 `print()` 메서드를 실행할 수 있다.[15][7]

C++11부터는 `override` 키워드를 사용하여 메서드가 기본 클래스의 메서드를 오버라이드하는지 컴파일러가 확인하도록 할 수 있다.[7] 또한, 슈퍼클래스에서 `final`로 정의된 메서드는 오버라이딩될 수 없다.[7]

C++는 하위 클래스가 재정의하려는 메서드의 상위 클래스 버전을 호출하기 위해 Java에서 사용할 수 있는 `super` 키워드를 가지고 있지 않다.[7] 대신, 부모 또는 기본 클래스의 이름과 범위 지정 연산자를 사용한다.[7]

== Java ==

자바에서 하위 클래스는 상위 클래스의 메서드와 동일한 시그니처(이름 및 매개변수 유형)를 가진 메서드를 포함하여 상위 클래스의 메서드를 재정의할 수 있다.[3] Java의 인스턴스 메서드는 기본적으로 가상 메서드이므로, 별도의 키워드 없이 오버라이딩이 가능하다.

하위 클래스에서 `super` 키워드를 사용하면 상위 클래스의 오버라이딩된 메서드를 명시적으로 호출할 수 있다.[3]

`final`로 선언된 메서드는 하위 클래스에서 오버라이딩할 수 없다. `private` 또는 `static`으로 선언된 메서드도 암시적으로 `final`이므로 오버라이딩할 수 없다. `final`로 선언된 클래스는 상속될 수 없다.[9]

Java SE 5부터 `@Override` 애너테이션을 사용하여 메서드가 오버라이드되었음을 컴파일러에게 알릴 수 있다. 이는 선택 사항이지만, 올바르게 오버라이드되지 않은 경우 컴파일 오류를 발생시켜 유용하다.

== C# ==

C#에서는 메서드 오버라이딩을 지원하지만, `override` 및 `virtual` 또는 `abstract` 한정자를 사용하여 명시적으로 요청해야 한다.[6] 하나의 메서드를 다른 메서드로 오버라이딩할 때 두 메서드의 타입 시그니처는 동일해야 하며, 클래스 메서드, 인덱서, 속성 및 이벤트 모두를 오버라이딩할 수 있다.[6]

C# 메서드 오버라이딩 예시


가상 메서드가 아니거나 정적 메서드는 오버라이딩할 수 없다. 오버라이딩된 기본 메서드는 `virtual`, `abstract`, 또는 `override`여야 한다.[6] 메서드 오버라이딩에 사용되는 한정자 외에도, C#은 상속된 속성 또는 메서드를 숨기는 것을 허용하는데, 이는 `new` 한정자를 추가하여 수행된다.[6]

C#의 오버라이딩 특징은 다음과 같다.[6]

  • 가상 메서드 및 추상 메서드를 오버라이딩할 때는 `override` 키워드를 지정해야 한다. 단, 인터페이스의 메서드를 구현하는 경우에는 `override`를 지정할 필요가 없다.
  • 메서드는 기본적으로 비가상이며, `virtual`을 지정하면 오버라이딩 가능한 가상 메서드가 된다.
  • 프로퍼티, 인덱서, 이벤트도, `virtual`로 한정된 경우에는 메서드와 마찬가지로 오버라이딩 대상이 된다.
  • `sealed` 키워드를 지정하면 오버라이딩을 금지할 수 있다.


== Python ==

파이썬에서는 서브클래스에서 슈퍼클래스와 동일한 이름의 메서드를 정의하면 메서드 오버라이딩이 된다.[16] 부모 클래스의 메서드를 호출하려면 `super()` 함수를 사용한다.[10]

== Ruby ==

루비에서, 서브클래스는 슈퍼클래스의 메소드를 오버라이드하는 메소드를 포함하며, 또한 오버라이딩 된 메소드에서 `super`를 호출함으로써 슈퍼클래스를 호출할 수 있다. 만약 오버라이딩된 메소드 오버라이딩 메소드의 외부에서 보존되게 하고 싶다면 `alias` 키워드를 `super_message`와 함께 사용할 수 있다.

== 델파이 ==

델파이에서 메소드 오버라이딩은 `override` 지시자를 통해 수행되지만, 해당 메소드가 `dynamic` 또는 `virtual` 지시자로 선언되어야 한다. `inherited` 키워드는 상위 클래스의 행동을 호출하기를 원할 때 반드시 호출되어야 한다.

== Ada ==

에이다는 기본적으로 메서드 오버라이딩을 제공한다. 조기 오류 감지(예: 오타)를 위해 메서드가 실제로 오버라이딩될 것으로 예상되는 시점 또는 그렇지 않은 시점을 지정할 수 있다. 이는 컴파일러에 의해 확인된다.

`overriding` 지시자를 사용하여 오버라이딩 여부를 명시하고, 컴파일러가 이를 확인한다.

== Eiffel ==

Eiffel에서 '''feature 재정의'''는 C++와 Java의 메소드 오버라이딩과 유사하다.[8] 재정의는 상속된 feature를 상속 클래스에서 다시 deferred되게 하는 '''undefinition''', defered(추상)된 feature에 대한 구현을 제공하는 '''실행'''과 함께 '''재선언'''으로 분류되는 세 가지 형태의 feature 적용 중 하나이다.[8] feature가 재정의될 때, feature 이름은 상속 클래스에 의해 유지되지만, 시그니처, 계약(사전 조건 및 사후 조건에 대한 제한 사항 준수), 그리고/또는 구현과 같은 feature의 속성은 상속 클래스에서 달라진다.[8] 상속 feature의 '''선행 feature'''라고 불리는 부모 클래스의 원래 feature가 effective하면, 상속 클래스에서 재정의된 feature는 effective하게 된다.[8] 선행 feature가 deferred이면, 상속 클래스의 feature는 deferred된다.[8]

feature를 재정의하려는 의도는 상속 클래스의 `inherit` 절에서 `redefine` 키워드를 사용하여 명시적으로 선언되어야 한다.[8]

`Precursor` 키워드를 사용하여 feature의 선행 feature에 접근할 수 있다.

== Kotlin ==

코틀린에서는 `override` 키워드를 사용하여 오버라이딩을 명시해야 한다. `open` 키워드로 선언된 함수만 오버라이딩할 수 있다.

2. 1. C++

C++에서는 부모 클래스의 메서드를 명시적으로 호출하기 위해 범위 지정 연산자(::)를 사용한다.[15] 예를 들어, 기본 클래스 `TRectangle`과 유도 클래스 `TBox`가 있을 때, `TBox`는 `TRectangle` 클래스의 `print()` 메서드를 오버라이드하며, 자신의 높이를 추가로 출력한다.[15] 이때 `TBox`의 `print()` 메서드 내에서 `TRectangle::print()`를 호출하여 부모 클래스의 `print()` 메서드를 실행할 수 있다.[15][7]

C++11부터는 `override` 키워드를 사용하여 메서드가 기본 클래스의 메서드를 오버라이드하는지 컴파일러가 확인하도록 할 수 있다.[7] 또한, 슈퍼클래스에서 `final`로 정의된 메서드는 오버라이딩될 수 없다.[7]

C++는 하위 클래스가 재정의하려는 메서드의 상위 클래스 버전을 호출하기 위해 Java에서 사용할 수 있는 `super` 키워드를 가지고 있지 않다.[7] 대신, 부모 또는 기본 클래스의 이름과 범위 지정 연산자를 사용한다.[7]

2. 2. Java

자바에서 하위 클래스는 상위 클래스의 메서드와 동일한 시그니처(이름 및 매개변수 유형)를 가진 메서드를 포함하여 상위 클래스의 메서드를 재정의할 수 있다.[3] Java의 인스턴스 메서드는 기본적으로 가상 메서드이므로, 별도의 키워드 없이 오버라이딩이 가능하다.

```java

class Thought {

public void message() {

System.out.println("I feel like I am diagonally parked in a parallel universe.");

}

}

public class Advice extends Thought {

@Override // Java 5의 @Override 어노테이션은 선택 사항이지만 유용합니다.

public void message() {

System.out.println("Warning: Dates in calendar are closer than they appear.");

}

}

```

위 예제에서 `Advice` 클래스는 `Thought` 클래스의 `message()` 메서드를 오버라이딩한다. `Thought` 타입의 변수에 `Advice` 객체를 할당하면, 오버라이딩된 `message()` 메서드가 호출된다.

```java

Thought parking = new Thought();

parking.message(); // "I feel like I am diagonally parked in a parallel universe." 출력

Thought dates = new Advice(); // 다형성

dates.message(); // "Warning: Dates in calendar are closer than they appear." 출력

```

하위 클래스에서 `super` 키워드를 사용하면 상위 클래스의 오버라이딩된 메서드를 명시적으로 호출할 수 있다.[3]

```java

public class Advice extends Thought {

@Override

public void message() {

System.out.println("Warning: Dates in calendar are closer than they appear.");

super.message(); // 상위 클래스 메서드 호출

}

}

```

`final`로 선언된 메서드는 하위 클래스에서 오버라이딩할 수 없다. `private` 또는 `static`으로 선언된 메서드도 암시적으로 `final`이므로 오버라이딩할 수 없다. `final`로 선언된 클래스는 상속될 수 없다.[9]

Java SE 5부터 `@Override` 애너테이션을 사용하여 메서드가 오버라이드되었음을 컴파일러에게 알릴 수 있다. 이는 선택 사항이지만, 올바르게 오버라이드되지 않은 경우 컴파일 오류를 발생시켜 유용하다.

2. 3. C#

C#에서는 메서드 오버라이딩을 지원하지만, `override` 및 `virtual` 또는 `abstract` 한정자를 사용하여 명시적으로 요청해야 한다.[6] 하나의 메서드를 다른 메서드로 오버라이딩할 때 두 메서드의 타입 시그니처는 동일해야 하며, 클래스 메서드, 인덱서, 속성 및 이벤트 모두를 오버라이딩할 수 있다.[6]

가상 메서드가 아니거나 정적 메서드는 오버라이딩할 수 없다. 오버라이딩된 기본 메서드는 `virtual`, `abstract`, 또는 `override`여야 한다.[6] 메서드 오버라이딩에 사용되는 한정자 외에도, C#은 상속된 속성 또는 메서드를 숨기는 것을 허용하는데, 이는 `new` 한정자를 추가하여 수행된다.[6]

C#의 오버라이딩 특징은 다음과 같다.[6]

  • 가상 메서드 및 추상 메서드를 오버라이딩할 때는 `override` 키워드를 지정해야 한다. 단, 인터페이스의 메서드를 구현하는 경우에는 `override`를 지정할 필요가 없다.
  • 메서드는 기본적으로 비가상이며, `virtual`을 지정하면 오버라이딩 가능한 가상 메서드가 된다.
  • 프로퍼티, 인덱서, 이벤트도, `virtual`로 한정된 경우에는 메서드와 마찬가지로 오버라이딩 대상이 된다.
  • `sealed` 키워드를 지정하면 오버라이딩을 금지할 수 있다.


```csharp

// 추상 기본 클래스.

abstract class Base {

// 기본적으로 비가상 메서드.

public void GoodMorning() { Console.WriteLine("Good morning, Base!"); }

// virtual을 지정하여 가상 메서드가 된다.

public virtual void Hello() { Console.WriteLine("Hello, Base!"); }

public virtual void Goodbye() { Console.WriteLine("Goodbye, Base!"); }

// 추상 메서드 (구현을 갖지 않음).

public abstract void GoodNight();

}

// 파생 클래스.

class Derived : Base {

// 비가상 메서드는 오버라이딩할 수 없다.

// 같은 이름의 메서드로 숨기는 경우, new를 지정한다.

// (여기서는 지정하지 않지만, 여기에 virtual을 지정하면 가상 메서드가 된다)

public new void GoodMorning() { Console.WriteLine("Good morning, Derived!"); }

// 가상 메서드를 오버라이딩한다.

// override 지정을 필수로 한다.

public override void Hello() { Console.WriteLine("Hello, Derived!"); }

// 가상 메서드를 오버라이딩한다.

// override와 함께 sealed를 지정하면, 이 클래스를 상속한 곳에서는 오버라이딩이 금지된다.

public override sealed void Goodbye() { Console.WriteLine("Goodbye, Derived!"); }

// 추상 메서드를 오버라이딩한다.

// override 지정을 필수로 한다.

public override void GoodNight() { Console.WriteLine("Good night, Derived!"); }

}

class DerivedDerived : Derived {

// 비가상 메서드는 오버라이딩 불가.

//public override void GoodMorning() { Console.WriteLine("Good morning, DerivedDerived!"); }

public override void Hello() { Console.WriteLine("Hello, DerivedDerived!"); }

// sealed된 메서드는 오버라이딩 불가.

//public override void Goodbye() { Console.WriteLine("Goodbye, DerivedDerived!"); }

public override void GoodNight() { Console.WriteLine("Good night, DerivedDerived!"); }

}

2. 4. Python

파이썬에서는 서브클래스에서 슈퍼클래스와 동일한 이름의 메서드를 정의하면 메서드 오버라이딩이 된다.[16] 부모 클래스의 메서드를 호출하려면 `super()` 함수를 사용한다.[10]

```python

class Thought(object):

def __init__(self):

pass

def message(self):

print "I feel like I am diagonally parked in a parallel universe."

class Advice(Thought):

def __init__(self):

super(Advice, self).__init__()

def message(self):

print "Warning: Dates in calendar are closer than they appear"

super(Advice, self).message()

```

위 예제에서 `Advice` 클래스는 `Thought` 클래스를 상속받고, `message` 메서드를 오버라이딩한다. `super(Advice, self).message()`를 통해 `Thought` 클래스의 `message` 메서드를 호출한다.

2. 5. Ruby

루비에서, 서브클래스는 슈퍼클래스의 메소드를 오버라이드하는 메소드를 포함하며, 또한 오버라이딩 된 메소드에서 `super`를 호출함으로써 슈퍼클래스를 호출할 수 있다. 만약 오버라이딩된 메소드 오버라이딩 메소드의 외부에서 보존되게 하고 싶다면 `alias` 키워드를 `super_message`와 함께 사용할 수 있다.

```ruby

class Thought

def message

puts "I feel like I am diagonally parked in a parallel universe."

end

end

class Advice < Thought

alias :super_message :message

def message

puts "Warning: Dates in calendar are closer than they appear"

super

end

end

2. 6. 델파이

델파이에서 메소드 오버라이딩은 `override` 지시자를 통해 수행되지만, 해당 메소드가 `dynamic` 또는 `virtual` 지시자로 선언되어야 한다. `inherited` 키워드는 상위 클래스의 행동을 호출하기를 원할 때 반드시 호출되어야 한다.

```pascal

type

TRectangle = class

private

FLength: Double;

FWidth: Double;

public

property Length read FLength write FLength;

property Width read FWidth write FWidth;

procedure Print; virtual;

end;

TBox = class(TRectangle)

public

procedure Print; override;

end;

2. 7. Ada

에이다는 기본적으로 메서드 오버라이딩을 제공한다. 조기 오류 감지(예: 오타)를 위해 메서드가 실제로 오버라이딩될 것으로 예상되는 시점 또는 그렇지 않은 시점을 지정할 수 있다. 이는 컴파일러에 의해 확인된다.

```ada

type T is new Controlled with ......;

procedure Op(Obj: in out T; Data: in Integer);

type NT is new T with null record;

overriding -- overriding indicator

procedure Op(Obj: in out NT; Data: in Integer);

overriding -- overriding indicator

procedure Op(Obj: in out NT; Data: in String);

  • - ^ compiler issues an error: subprogram "Op" is not overriding

```

`overriding` 지시자를 사용하여 오버라이딩 여부를 명시하고, 컴파일러가 이를 확인한다.

2. 8. Eiffel

Eiffel에서 '''feature 재정의'''는 C++와 Java의 메소드 오버라이딩과 유사하다.[8] 재정의는 상속된 feature를 상속 클래스에서 다시 deferred되게 하는 '''undefinition''', defered(추상)된 feature에 대한 구현을 제공하는 '''실행'''과 함께 '''재선언'''으로 분류되는 세 가지 형태의 feature 적용 중 하나이다.[8] feature가 재정의될 때, feature 이름은 상속 클래스에 의해 유지되지만, 시그니처, 계약(사전 조건 및 사후 조건에 대한 제한 사항 준수), 그리고/또는 구현과 같은 feature의 속성은 상속 클래스에서 달라진다.[8] 상속 feature의 '''선행 feature'''라고 불리는 부모 클래스의 원래 feature가 effective하면, 상속 클래스에서 재정의된 feature는 effective하게 된다.[8] 선행 feature가 deferred이면, 상속 클래스의 feature는 deferred된다.[8]

feature를 재정의하려는 의도는 상속 클래스의 `inherit` 절에서 `redefine` 키워드를 사용하여 명시적으로 선언되어야 한다.[8]

`Precursor` 키워드를 사용하여 feature의 선행 feature에 접근할 수 있다.

2. 9. Kotlin

코틀린에서는 `override` 키워드를 사용하여 오버라이딩을 명시해야 한다. `open` 키워드로 선언된 함수만 오버라이딩할 수 있다.

```kotlin

open class Parent(val a : Int) {

open fun myFun() = println(a)

}

class Child(val b : Int) : Parent(b) {

override fun myFun() = println("overrided method")

}

```

위 예제에서 `Child` 클래스는 `Parent` 클래스를 상속받고, `myFun()` 함수를 오버라이딩한다. `Parent` 클래스의 `myFun()` 함수는 `open` 키워드로 선언되어 오버라이딩이 가능하다. `Child` 클래스에서 `myFun()` 함수는 `override` 키워드를 사용하여 오버라이딩을 명시한다.

3. 오버라이딩 시 주의사항 (언어별)

슈퍼클래스와 이를 상속하는 서브클래스를 정의할 때, Java나 C++에서는 오버라이딩과 관련된 문제가 발생할 수 있으므로 주의해야 한다(특히 슈퍼클래스의 구현자와 서브클래스의 구현자가 다른 경우). Java의 인스턴스 메서드는 가상 메서드이며, 나중에 슈퍼클래스에 메서드를 추가했을 때, 해당 메서드와 동일한 시그니처의 메서드가 이미 서브클래스에 존재하면, 오버라이딩할 의도가 없었음에도 관련 없는 메서드를 오버라이딩해버리는 문제가 발생한다. 반대로 오버라이딩할 의도가 있었음에도, 슈퍼클래스의 메서드 시그니처 또는 접근성 변경이나, 서브클래스의 메서드 정의 시의 오타 등으로 인해 올바르게 오버라이딩되지 않는 문제도 발생한다. 후자의 문제를 회피하기 위해 Java에서는 `@Override` 지정을 권장하지만, 하위 호환성을 유지하기 위해 어노테이션 지정은 필수가 아니다. C++에서도 C++11에서 `override` 수식자가 도입되었지만, `override` 수식자 지정은 선택 사항이며 필수가 아니다.

```java

// 기본 클래스.

class Base {

public Base() {

System.out.println("Base.Base()");

this.init();

}

// 접근 제한자를 변경하여 파생 클래스에서 보이도록 하면,

// Derived 에서 의도하지 않게 오버라이딩하게 된다.

// 결과적으로, 생성자의 동작이 바뀌어버린다.

// 실수로 오버라이딩하는 것을 방지하려면, final 지정을 해야 한다.

private void init() {

System.out.println("Base.init()");

}

}

// 파생 클래스.

class Derived extends Base {

public Derived() {

System.out.println("Derived.Derived()");

this.init();

}

// 만약 기본 클래스에 동일한 이름의 가시적 메서드가 정의되어 있다면, 오버라이딩한다.

public void init() {

System.out.println("Derived.init()");

}

}

public class Main {

public static void main(String[] args) {

Derived derived = new Derived();

}

}

```

C#에서는 메서드가 기본적으로 비가상이며, 또한 오버라이딩하려면 처음부터 `override` 수식자가 필수이므로 이 문제는 발생하지 않는다. 기본 클래스를 변경하더라도, 파괴적인 변경으로 이어지기 어렵다.

```csharp

// 기본 클래스.

class Base {

public Base() {

System.Console.WriteLine("Base.Base()");

this.Init();

}

// 접근 제한자를 변경하여 파생 클래스에서 보이도록 해도,

// Derived 에서 의도하지 않게 오버라이딩하게 되는 일은 없다.

// 만약 기본 클래스에서 virtual 지정을 하더라도, 파생 클래스에서 override 지정을 필수로 하기 때문에,

// 의도하지 않게 오버라이딩하게 되는 일은 없다.

private void Init() {

System.Console.WriteLine("Base.Init()");

}

}

// 파생 클래스.

class Derived : Base {

public Derived() {

System.Console.WriteLine("Derived.Derived()");

this.Init();

}

// 만약 기본 클래스에 동일한 이름의 가시적 메서드가 정의되어 있다면, 숨긴다.

// new 지정을 필수로 할 필요는 없지만, new 지정을 하지 않고 숨긴 경우에는 컴파일러가 경고를 보낸다.

public void Init() {

System.Console.WriteLine("Derived.Init()");

}

}

public class Test {

public static void Main() {

Derived derived = new Derived();

}

}

```

Kotlin[11]이나 Swift[12]와 같은 후발 언어에서는 C#과 마찬가지로 오버라이딩에는 `override` 지정을 필수로 한다.

3. 1. Java 및 C++

슈퍼클래스와 이를 상속하는 서브클래스를 정의할 때, Java나 C++에서는 오버라이딩과 관련된 문제가 발생할 수 있으므로 주의해야 한다(특히 슈퍼클래스의 구현자와 서브클래스의 구현자가 다른 경우). Java의 인스턴스 메서드는 가상 메서드이며, 나중에 슈퍼클래스에 메서드를 추가했을 때, 해당 메서드와 동일한 시그니처의 메서드가 이미 서브클래스에 존재하면, 오버라이딩할 의도가 없었음에도 관련 없는 메서드를 오버라이딩해버리는 문제가 발생한다. 반대로 오버라이딩할 의도가 있었음에도, 슈퍼클래스의 메서드 시그니처 또는 접근성 변경이나, 서브클래스의 메서드 정의 시의 오타 등으로 인해 올바르게 오버라이딩되지 않는 문제도 발생한다. 후자의 문제를 회피하기 위해 Java에서는 `@Override` 지정을 권장하지만, 하위 호환성을 유지하기 위해 어노테이션 지정은 필수가 아니다. C++에서도 C++11에서 `override` 수식자가 도입되었지만, `override` 수식자 지정은 선택 사항이며 필수가 아니다.

```java

// 기본 클래스.

class Base {

public Base() {

System.out.println("Base.Base()");

this.init();

}

// 접근 제한자를 변경하여 파생 클래스에서 보이도록 하면,

// Derived 에서 의도하지 않게 오버라이딩하게 된다.

// 결과적으로, 생성자의 동작이 바뀌어버린다.

// 실수로 오버라이딩하는 것을 방지하려면, final 지정을 해야 한다.

private void init() {

System.out.println("Base.init()");

}

}

// 파생 클래스.

class Derived extends Base {

public Derived() {

System.out.println("Derived.Derived()");

this.init();

}

// 만약 기본 클래스에 동일한 이름의 가시적 메서드가 정의되어 있다면, 오버라이딩한다.

public void init() {

System.out.println("Derived.init()");

}

}

public class Main {

public static void main(String[] args) {

Derived derived = new Derived();

}

}

```

C#에서는 메서드가 기본적으로 비가상이며, 또한 오버라이딩하려면 처음부터 `override` 수식자가 필수이므로 이 문제는 발생하지 않는다. 기본 클래스를 변경하더라도, 파괴적인 변경으로 이어지기 어렵다.

```csharp

// 기본 클래스.

class Base {

public Base() {

System.Console.WriteLine("Base.Base()");

this.Init();

}

// 접근 제한자를 변경하여 파생 클래스에서 보이도록 해도,

// Derived 에서 의도하지 않게 오버라이딩하게 되는 일은 없다.

// 만약 기본 클래스에서 virtual 지정을 하더라도, 파생 클래스에서 override 지정을 필수로 하기 때문에,

// 의도하지 않게 오버라이딩하게 되는 일은 없다.

private void Init() {

System.Console.WriteLine("Base.Init()");

}

}

// 파생 클래스.

class Derived : Base {

public Derived() {

System.Console.WriteLine("Derived.Derived()");

this.Init();

}

// 만약 기본 클래스에 동일한 이름의 가시적 메서드가 정의되어 있다면, 숨긴다.

// new 지정을 필수로 할 필요는 없지만, new 지정을 하지 않고 숨긴 경우에는 컴파일러가 경고를 보낸다.

public void Init() {

System.Console.WriteLine("Derived.Init()");

}

}

public class Test {

public static void Main() {

Derived derived = new Derived();

}

}

```

Kotlin[11]이나 Swift[12]와 같은 후발 언어에서는 C#과 마찬가지로 오버라이딩에는 `override` 지정을 필수로 한다.

3. 2. C#, Kotlin, Swift

C#, Kotlin[11], Swift[12]와 같은 언어에서는 오버라이딩을 위해 `override` 지정을 필수로 요구한다. 이는 슈퍼클래스와 서브클래스를 정의할 때, Java나 C++에서 발생할 수 있는 오버라이딩 관련 문제, 즉 의도하지 않은 오버라이딩이나 오타 등으로 인한 오버라이딩 실패를 방지한다. C#에서 메서드는 기본적으로 비가상이며, 오버라이딩을 위해서는 `override` 수식자가 반드시 필요하다. 이러한 방식은 기본 클래스를 변경하더라도 파괴적인 변경으로 이어지는 것을 방지하는 데 도움이 된다.

참조

[1] 서적 2015 IEEE International Conference on Consumer Electronics - Taiwan 2015
[2] 서적 Flanagan 2002
[3] 서적 Lewis & Loftus 2006
[4] 서적 2011 26th IEEE/ACM International Conference on Automated Software Engineering (ASE 2011) 2011
[5] 간행물 Residual investigation: Predictive and precise bug detection 2014
[6] 웹사이트 Advanced C#: Overriding of Methods http://ssw.jku.at/Te[...] Institut für Systemsoftware, Johannes Kepler Universität Linz, Fachbereich Informatik 2002-03-25
[7] 서적 Malik 2006
[8] 서적 Meyer 2009
[9] 서적 Deitel & Deitel 2001
[10] 웹사이트 Python https://docs.python.[...] 2018-10-26
[11] 웹사이트 クラスと継承 - Kotlin Programming Language https://dogwood008.g[...]
[12] 웹사이트 継承(Inheritance) · The Swift Programming Language日本語版 https://www.swiftlan[...]
[13] 서적 Flanagan 2002
[14] 서적 Lewis & Loftus 2006
[15] 서적 Malik 2006
[16] 웹사이트 super().method https://docs.python.[...] 2018-10-26



본 사이트는 AI가 위키백과와 뉴스 기사,정부 간행물,학술 논문등을 바탕으로 정보를 가공하여 제공하는 백과사전형 서비스입니다.
모든 문서는 AI에 의해 자동 생성되며, CC BY-SA 4.0 라이선스에 따라 이용할 수 있습니다.
하지만, 위키백과나 뉴스 기사 자체에 오류, 부정확한 정보, 또는 가짜 뉴스가 포함될 수 있으며, AI는 이러한 내용을 완벽하게 걸러내지 못할 수 있습니다.
따라서 제공되는 정보에 일부 오류나 편향이 있을 수 있으므로, 중요한 정보는 반드시 다른 출처를 통해 교차 검증하시기 바랍니다.

문의하기 : help@durumis.com