해당 챕터에서는 코틀린에서 class를 다루는 법에 대해 더 깊은 이해를 가질 것이다. 코틀린의 class와 interface는 자바의 그것과 약간은 다르다. 이제부터 그 차이점을 알아보도록 하자.
코틀린의 인터페이스는 추상 메소드의 구현을 필요로 한다는 점에서 자바 8의 것과 비슷한데, 단지 상태를 가지고 있지 않다는 점이 다르다.
//인터페이스
interface Clickable {
fun click()
}
//인터페이스 구현
class Button : Clickable {
override fun click() = println("I was clicked")
}
>>> Button().click()
I was clicked
또한 코틀린에서는 인터페이스를 구현하기 위해서 implements
나 extends
를 사용하는 대신 콜론(:)
을 사용한다.
자바와는 다르게 코틀린에서는 override
키워드를 사용하는 것이 필수적이다. 이는 실수로 메소드를 오버라이드하는 상황을 방지해준다. 또한, 인터페이스의 메소드는 default 구현이 가능하다. 이때 자바는 default
키워드로 이를 명시해야 하지만, 코틀린은 그럴 필요가 없다.
//인터페이스
interface Clickable {
fun click() //반드시 구현해야 함
fun showOff() = println("I'm clickable!") //디폴트 메소드가 있으므로, 그대로 사용 가능
}
이때 다른 인터페이스(Focusable이라고 하겠다)에서도 showOff 메소드를 가지게 될 경우 컴파일 오류가 발생할 수 있다. 따라서 이 경우에는 자바와 마찬가지로, super
키워드를 사용해야 한다. 이때 super의 앞에 인터페이스 이름을 적는 자바와 달리, <>안에 인터페이스 이름을 적어야 한다.
//showOff 메소드의 구현
class Button : Clickable, Focusable {
override fun click() = println("I was clicked")
override fun showOff() {
super<Clickable>.showOff()
super<Focusable>.showOff()
}
}
자바의 경우 모든 클래스의 서브 클래스를 생성하는 것이 가능하고, 모든 메소드의 오버라이딩이 가능하다(final로 선언되지 않은 이상). 그런데 이는 편리하기도 하지만 한편으로는 문제를 일으킬 수 있다. 자바에서는 가끔씩 취약한 기반 클래스(fragile base class) 문제가 발생한다. 이는 다음과 같은 문제다.
하위 클래스가 기반 클래스에 대해 가졌던 가정이 기반 클래스를 변경함으로써 깨져버린 경우에 생긴다. 어떤 클래스가 자신을 상속하는 방법에 대해 정확한 규칙을 제공하지 않는다면 그 클래스의 클라이언트는 기반 클래스를 작성한 사람의 의도와 다른 방식으로 메서드를 오버라이드할 위험이 있다.
이를 막기 위해서 자바를 사용할 때는 “상속을 위한 설계와 문서를 갖추거나, 그럴 수 없다면 상속을 금지”하는 것이 올바른 방식이다. 코틀린도 이와 같은 철학을 따른다. 코틀린의 매소트는 디폴트로 final
이기 때문이다. 만약 어떤 클래스가 서브클래스의 생성을 허용한다면, 이를 open
으로 명시해야 한다.
//서브 클래스가 상속 가능함을 명시함.
open class RichButton : Clickable {
fun disable() {} //디폴트가 final이므로, 오버라이드 불가
open fun animate() {} //서브 클래스에서 오버라이드함을 명시함.
override fun click() {}
final override fun click() {} //final이 없는 오버라이드는 기본으로 open임으로, final을 명시해야 함
}
<aside> 📌 이전에 스마트 캐스팅을 위해선 클래스의 프로퍼티가 val이면서 커스텀 접근자를 구현하지 않아야 한다. 클래스도 마찬가지로 만약 클래스가 open이라면 스마트 캐스트는 불가하다.
</aside>
만약 abstract
로 선언한 클래스가 있다면, 자바와 마찬가지로, 이는 인스턴스화하는 것이 불가능하다. 추상 클래스의 추상 맴버는 반드시 오버라이드 되어야 하며, 따라서 항상 open
이다. (이를 꼭 명시할 필요는 없다.)
가시성 변경자는 코드 베이스의 컨트롤을 돕는다. 자바와 비슷하게, public
, protected
, 그리고 private
변경자가 있다. 그러나 디폴트 변경자가 다른데, 만약 명시하지 않으면 public
이 되기 때문이다. 또한 자바가 package를 가시성 컨트롤을 위해 사용하는 것과 달리, 코틀린에서는 단순히 코드를 정돈하기 위해서 사용한다.
또한 코틀린은 모듈 내부에서만 사용할 수 있는 internal
접근자를 따로 제공한다. 이는 모듈 내부에서만 가시적이라는 뜻으로, 이때 모듈은 같이 컴파일되는 코틀린 파일 집합을 뜻한다. 이는 자바보다 캡슐화
를 효과적으로 지원한다. 자바에서는 같은 패키지 안에 코드가 작성될 경우 캡슐화가 깨질 수 있기 때문이다.