TypeClass 와 Interface의 차이점 With Kotlin

Lazysoul
5 min readMar 19, 2017

--

TypeClass는 Haskell에서 등장했습니다.

a type class is a type system construct that supports ad hoc polymorphism.

번역하면 다음과 같습니다.

타입 클래스는 ad hoc 다형성을 지원하는 타입 시스템 구조이다.

ad hoc 이라는 단어가 종종 보입니다. ad hoc 이란 ‘특정한 목적을가진', ‘임시 방편' 이란 의미를 가진 라틴어라고 합니다. 그렇다면 ad hoc 다형성이란 무엇을 말하는 걸까요?

간단히 말하면 오버로딩을 의미합니다. 오버로딩이란 ‘같은 이름을 갖지만 매개변수나 리턴타입이 각각 다를수 있다’ 를 말합니다. 함수 이름을 특정 행위에 대한 선언이라고 한다면, 특정 행위를 다양하게 구현을 하는 것입니다. (매개변수나 리턴타입에 상관없이)

매개변수화한 타입(Generic)을 사용하기 때문에 ad hoc 다형성을 지원한다고 이해하면 될것 같습니다.

동등성을 체크하는 타입클래스 Eq를 예로 들어보겠습니다.

하스켈 코드를 설명하면 다음과 같습니다.

  • a는 타입클래스 Eq를 매개변수화 한 타입으로 제약합니다.
  • 타입클래스 Eq는 == 와 /= 라는 두 연산을 같습니다. 두 연산은 Eq라는 타입클래스를 가지고 있는 타입 2개를 입력받아 Boo값을 반환합니다. 즉 같은 type 의 두 값을 비교해 Bool값을 반환 합니다.

Integer가 타입클래스 Eq를 포함(인스턴스화) 하려면 다음과 같이 코드를 작성할 수 있습니다.

타입클래스를 인스턴스화 하면 Implicit하게 타입클래스의 기능을 갖습니다.

하스켈의 타입클래스는 원하는 클래스에 언제든지 Implicit 하게 타입클래스를 정의 할 수 있습니다. 하지만 interface는 상속받는 즉시 상속받는 클래스 내부에서 구현을 해야 합니다. 선언을 하는 타이밍과 어디서 하느냐가 차이 인것 같습니다.

그렇다면 타입클래스가 어떤 경우에 이점이 있는지 알아보겠습니다. 예를 들어 Some 이라는 라이브러리에 있는 Some class를 사용하고 있었습니다. Some 클래스도 타입클래스 Eq가 필요해졌습니다. Some은 내가 정의한 클래스가 아니니 수정이 불가능합니다. 타입클래스를 활용하면 Some 클래스에도 Eq 타입클래스를 적용하는게 가능합니다.

Some 클래스에 Eq 타입클래스를 인스턴스화 하면 마치 Some 클래스가 Eq를 가지고 있는 것처럼 동작이 가능합니다. 다형성도 유지하고 내가 작성하지 않은 Some 클래스에도 Eq 타입클래스가 적용 가능합니다.

그렇다면 Kotlin 도 타입클래스 개념이 있을까요? 예제를 통해서 살펴보겠습니다.

Eq를 상속받은 코드는 다음과 같습니다.

아직까지는 인터페이스도 문제가 없어보입니다. Some2 라는 클래스를 사용하고 있는데 Some2 에도 Eq가 갖는 행위들이 필요 할 수 있습니다.

Kotlin 에서 하스켈의 타입클래스를 흉내내려면 3가지 방법이 있을 것 같습니다.

  • Some2를 똑같이 만들고 Eq를 상속받는 방법

코드에 문제는 없지만… 매우 비효율적인 방법입니다.

  • Some2에 확장 함수를 만들어 구현하는 방법

결과는 같고 코드도 비효율 적이지 않습니다. 하지만 추상화를 통한 다형성을 제공하지 못합니다.

SayEq 함수를 활용해 타입매개화 변수 Eq를 활용하려면 Some2는 불가능합니다.

또 다른 방법도 있습니다. 특정 타입대해 상위 Interface Eq를 정의해서 재사용하는 방법입니다.

Int타입에 대해 미리 구현을 합니다.

하스켈의 타입클래스 처럼 Implict 하진 않지만, 코드 중복도 제거하고, 다형성도 만족합니다.

정리

  • 타입클래스와 인터페이스 모두 다형성을 지원합니다.
  • 타입 클래스와 인터페이스는 행위에 대한 선언만하고 실제 구현은 상속받은 클래스가 구현하는 점은 같습니다.
  • 타입클래스는 Implicit하게 행위를 구현합니다.
  • 인터페이스는 상속받는 즉시 내부에서 행위를 구현합니다.
  • Kotlin은 하스켈의 타입클래스 개념을 흉내낼 수는 있지만, 똑같이 구현하는 것은 불가능 합니다.

Contents

--

--