프로그래밍Kotlin 개발자

Kotlin에서 인터페이스 위임을 위한 'by' 연산자는 어떻게 작동할까요? 인터페이스 위임과 속성 위임의 차이점은 무엇이며, 장단점은 무엇인지 코드 예제를 제시하세요.

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

답변.

by 연산자를 사용한 인터페이스 위임은 클래스가 인터페이스 호출을 특정 대리자 객체에 전달할 수 있게 해줍니다. 이는 코드 중복을 줄이고 조합 패턴(composition)을 구현합니다.

예제:

interface Logger { fun log(message: String) } class ConsoleLogger: Logger { override fun log(message: String) = println("LOG: $message") } class Service(logger: Logger): Logger by logger { fun doWork() { log("Service is working") } } val service = Service(ConsoleLogger()) service.doWork() // LOG: Service is working

속성 위임과의 차이점:

  • 인터페이스 위임은 클래스와 모든 인터페이스 구성원에게 적용됩니다.
  • 속성 위임(val/var x by ...)은 특정 속성에 적용되며, 대리자 인터페이스 (예: ReadWriteProperty)의 구현이 필요합니다.
  • 인터페이스 위임은 구현이 간결하지만 대리자의 모든 API를 노출합니다.

장점:

  • 데코레이터 패턴 및 위임 수행이 크게 간단해집니다.
  • 조합을 통해 표준 인터페이스의 동작을 변경할 수 있습니다.

단점:

  • 인터페이스의 모든 메서드는 항상 위임되며, 명시적으로 재정의하지 않고는 개별 호출을 "가로채기"가 불가능합니다.
  • 동일한 메서드를 가진 여러 인터페이스를 상속받을 경우 모호성이 발생할 수 있습니다.

함정 질문.

by를 사용한 인터페이스 위임은 객체를 필드를 통해 전달하여 인터페이스를 구현하는 것과 어떻게 다릅니까?

답변: 위임(by)은 대리자 객체를 통해 자동으로 모든 인터페이스 메서드를 구현합니다. 반면, 단순히 대리자 객체를 필드로 저장하고 수동으로 메서드를 호출하면 인터페이스의 각 메서드를 수동으로 작성해야 하며, 이는 중복 및 오류로 이어질 수 있습니다. 또한, by로 위임하면 가독성이 높아지고 보일러플레이트 코드가 줄어듭니다:

// 위임 없이 class Service2(private val logger: Logger): Logger { override fun log(message: String) = logger.log(message) }

이 주제에 대한 잘못된 이해로 인한 실제 오류 예:


이야기

프로젝트에서 Logger 인터페이스의 데코레이터 패턴을 수동으로 구현하려고 했는데, 추가된 인터페이스 메서드를 구현하는 것을 잊었습니다. 프로젝트는 컴파일되었지만, 새 기능은 작동하지 않았습니다. 왜냐하면 구현이 "빈 것"으로 존재했기 때문입니다. by를 통한 인터페이스 위임은 이 오류를 피할 수 있도록 해줬을 것입니다: 모든 새로운 메서드는 자동으로 대리자에 의해 구현됩니다.


이야기

by를 통해 인터페이스를 위임할 때, 개발자가 인터페이스 메서드 중 하나를 재정의했지만 나머지 메서드가 여전히 대리자를 통해 호출된다는 것을 잊었습니다. 결과적으로 일부 기능이 "비정상적"으로 작동하게 되었고, 비즈니스 메서드의 논리에서 이 오류는 오랫동안 포착되지 않았습니다.


이야기

여러 인터페이스를 by를 통해 위임하려고 했으나, 겹치는 메서드로 인해 충돌이 발생했습니다. 컴파일러가 모호성 오류를 발생시켰고, 중복된 메서드를 명시적으로 재정의해야 프로젝트가 빌드되었습니다.