프로그래밍코틀린 개발자

코틀린에서 일반 클래스, 추상 클래스 및 인터페이스의 차이점은 무엇이며, 언제 어떤 도구를 적용해야 합니까?

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

답변.

질문 배경:

코틀린은 자바의 장점과 JVM의 함수형 상속을 결합하였습니다. 일반 클래스는 표준 구조로 선언되며, 추상 클래스는 기본 구현이 있는 불완전한 템플릿을 생성할 수 있고, 인터페이스는 상태 없이 동작의 다중 상속을 지원합니다.

문제:

클래스, 추상 클래스 및 인터페이스 간의 올바른 선택은 애플리케이션의 아키텍처, 코드의 세분화 및 확장성을 결정합니다. 잘못된 상속은 테스트와 향후 수정의 복잡성을 초래합니다.

해결책:

코틀린에서는:

  • 일반 클래스: 구조와 동작을 정의합니다. open으로 선언하면 상속할 수 있습니다.
  • 추상 클래스: 직접 생성할 수 없습니다. 구현 및/또는 추상(본문 없는) 메서드를 포함할 수 있습니다.
  • 인터페이스: 암묵적으로 열려 있으며, 계약을 구현하고 메서드 구현을 허용하지만 상태를 저장할 수 없습니다(백킹 필드 없는 속성만 허용).

코드 예:

interface Drawable { fun draw() } abstract class Shape(var color: String) : Drawable { abstract fun calcArea(): Double override fun draw() = println("Shape drawn") } class Circle(color: String, val radius: Double) : Shape(color) { override fun calcArea() = Math.PI * radius * radius }

주요 특징:

  • 인터페이스는 다중 구현을 허용하고, 추상 클래스는 단일 구현만 허용합니다.
  • 인터페이스는 상태를 저장할 수 없고, 추상 클래스는 상태를 저장할 수 있습니다.
  • 추상 클래스는 일부 인터페이스를 구현하고 고유한 일반 로직을 포함할 수 있습니다.

교묘한 질문들.

인터페이스는 백킹 필드가 있는 속성을 포함할 수 있나요?

아니요, 속성의 서명만 정의할 수 있으며 데이터를 저장할 수 없습니다 — 백킹 필드 없는 속성만 허용됩니다.

여러 클래스로부터 상속받을 수 있나요?

아니요, 코틀린은 클래스의 단일 상속만 지원하지만 인터페이스의 다중 구현은 지원합니다.

인터페이스에 생성자를 선언할 수 있나요?

아니요, 인터페이스는 상태를 저장하지 않기 때문에 생성자를 지원하지 않습니다 — 오직 동작 계약만 존재합니다.

일반적인 오류 및 안티패턴

  • 필요 없이 인터페이스 대신 추상 클래스를 사용하는 것
  • 인터페이스에서 상태를 저장하려는 시도(불가능하지만 디자인 중에 자주 실수함)
  • 확장을 어렵게 만드는 클래스 계층 설계

실제 사례

부정적인 케이스

애플리케이션에서 모든 공통 기능을 추상 클래스에 넣었으나 내부 논리나 상태가 없는 경우, 단지 공통 계약이 필요했습니다.

장점:

  • 공통 논리를 변경하기 위한 단일 지점

단점:

  • 다중 상속 문제, 다른 구조와의 통합 어려움

긍정적인 케이스

필요한 계약만 인터페이스로 분리하고, 추상 클래스는 구현이 필요한 공통 속성과 메서드로 제한했습니다.

장점:

  • 유연한 확장, 모듈성, 깔끔한 계약

단점:

  • 초기 단계에서의 설계 필요