프로그래밍Kotlin 개발자

Kotlin에서 'override' 키워드는 어떻게 작동합니까? 재정의 메커니즘, 컴파일러의 요구 사항, 관련 제한 사항 및 전형적인 오류 예제를 설명하십시오.

Hintsage AI 어시스턴트로 면접 통과

답변.

질문 배경:

메서드 재정의는 OOP의 기초이지만, Java에서는 원래 override가 필수가 아니었습니다. Kotlin은 코드의 명확성을 높이고 상속 시 우연한 오류를 피하기 위해 override 사용을 필수로 하는 엄격한 타입 언어입니다.

문제:

명시적으로 override를 지정하지 않으면 인터페이스/클래스를 설명할 때 이름, 타입 또는 수정자에 오타가 쉽게 발생할 수 있습니다. 프로그램이 중단되지는 않지만 기대하는 재정의가 작동하지 않습니다. Kotlin은 이 문제를 근본적으로 해결합니다.

해결책:

Kotlin에서는 메서드를 재정의할 수 있도록 하려면 해당 메서드를 open(또는 abstract/interface)으로 선언해야 합니다. 재정의를 위해서는 반드시 override를 작성해야 합니다. 시그니처가 일치하지 않으면 컴파일 오류가 발생합니다. 이는 대부분의 전형적인 Java 버그를 예방합니다.

코드 예제:

open class Base { open fun greet() { println("Hello!") } } class Child : Base() { override fun greet() { println("Hi!") } }

주요 특징:

  • open/abstract/interface로 표시된 메서드만 재정의할 수 있습니다.
  • override 사용은 필수이며 명시적이어야 합니다.
  • open 없이 재정의를 시도하면 컴파일 오류가 발생합니다.

트릭 질문들.

override를 잊으면 우연히 함수를 재정의할 수 있나요?

아니요. override를 놓치면 선언된 메서드는 클래스의 새로운 메서드로 간주되며 재정의가 발생하지 않습니다. 만약 base 메서드에 open이 있을 경우 컴파일러는 오류를 발생시킵니다.

코드 예제:

open class A { open fun test() {} } class B : A() { fun test() {} // 재정의하지 않음! test2()와 동일함. }

자신의 메서드가 부모보다 더 엄격한 가시성을 가질 수 있습니까?

아니요. 재정의되는 메서드의 가시성 범위를 좁힐 수 없습니다. 예를 들어, 기본 메서드가 public인 경우, 재정의는 private/protected/internal일 수 없습니다. 컴파일러는 오류를 발생시킵니다.

재정의된 구성 요소가 final일 수 있나요?

네! 더 이상의 재정의를 원하지 않으면 final을 추가하십시오:

class D : Base() { final override fun greet() { //... } }

전형적인 오류 및 안티 패턴

  • override를 잊음: 함수가 재정의가 아닌 새로운 메서드로 간주됨
  • 비-open 메서드를 재정의하려고 시도 — 컴파일 오류
  • 시그니처 오류: override는 정확한 매개변수 및 반환 타입 일치를 요구함

실생활 예시

부정적인 케이스

Java에서:

public class Parent {void foo(){} } public class Child extends Parent {void foo(int x){} }

재정의가 기대되지만 실제로는 오버로딩입니다. 호출은 잘못된 메서드로 진행됩니다.

장점:

  • 유연성, 불필요한 코드 감소

단점:

  • 대규모 프로젝트에서 쉽게 감지되지 않는 오류

긍정적인 케이스

Kotlin에서:

open class Parent { open fun foo() {} } class Child : Parent() { override fun foo() { /*...*/ } }

장점:

  • 명시적인 재정의 가능성
  • 우연한 오류에 대한 최대한의 보호

단점:

  • 추가적인 키워드, 조금 더 긴 구문