코틀린 인터페이스
코틀린 인터페이스는 자바8과 비슷하게 추상 메소드 뿐만 아니라 구현이 있는 메소드도 정의할 수 있다. 다만 인터페이스에는 아무런 상태(필드)도 들어갈 수 없다.
1 | interface Clickable { |
콜론(:)
을 붙여 클래스 확장과 인터페이스를 구현 모두를 처리한다.override
변경자는 @Override 애노테이션과 동일하게 오버라이드 표시를 하지만 오버라이드 시반드시 사용
해야 한다.- showOff와 같이
디폴트 함수
를 제공한다.
인터페이스는 자바와 동일하게 하나의 클래스가 여러 인터페이스를 구현할 수 있는데 동일한 인터페이스의 디폴트 함수가 있을 경우 코틀린에서는 컴파일 에러로 사용자에게 하위 클래스에 직접 구현하게 강제한다.
1 | interfacle Focusable { |
- Clickable, Focusable의
showOff
함수가 동일하므로 오버라이드 하였다. - 상위 타입 호출 시 자바와는 다르게
super<>
를 사용한다. (자바는 Clickable.super.showOff()처럼 호출한다)
기본적으로 final
코틀린에서는 자바와는 다르게 기본적으로 아무것도 명시하지 않을 시 모든 클래스와 함수는 final
이다. 그 이유는 취약한 기반 클래스(fragile base class)
라는 문제를 기반하기 때문이다. 이 문제는 하위 클래스가 기반 클래스에 대해 가졌던 가정이 기반 클래스를 변경함으로써 깨져버린 경우에 생긴다. 즉 Effective Java에서처럼 상속을 위한 설계와 문서를 갖추거나, 그럴수 없다면 상속을 금지하라
라는 철학을 따라 기본적으로 모두 final
이다.
open
어떤 클래스의 상속을 허용하려면 open
변경자를 붙여야 한다. 함수도 마찬가지이다.
1 | open class RightButton : Clickable { |
- disable함수는
오버라이드 불가
이다. - animate함수는 열려있으므로
오버라이드 가능
이다. - click함수는 오버라이드 함수므로
기본적으로 열려
있다. - RightButton클래스는 열려 있으므로
상속이 가능
하다.
abstract
추상 클래스를 정의할 땐 abstract 변경자
를 사용한다. 추상 클래스 및 추상 멤버는 inteface와 동일하게 기본적으로 모두 열려
있다. 그러므로 open 변경자를 명시할 필요가 없다.
1 | abstract class Animated { |
- abstract 클래스이므로
상속이 가능
하다. - animate함수는 추상함수이므로
오버라이드가 가능
하다. - stopAnimating함수는 비추상 함수이지만
open이므로 오버라이드가 가능
하다 - animateTwice함수는 비추상 함수이므로
오버라이드가 불가능
하다.
가시성 변경자 : 기본적으로 공개
- 아무 변경자도 없는 경우 선언은 모두 public이다.
- internal 변경자는 모듈 내부에서만 볼 수 있음을 의미한다.
- 가시성은 public > internal > protected > private 순서이다.
1
2
3
4
5
6
7
8
9internal open class TalkativeButton : Fucosable {
private fun yell() = println("Hey!")
protected fun whisper() = println("Let's talk!")
}
fun TalkativeButton.giveSpeech() {
yell()
whisper()
}- giveSpeech 함수는 확장 함수로 public이 기본이므로 internal TalkativeButton 수신 타입을
확장 할 수 없다
. - yell함수는 private이므로 public 함수에서
접근이 불가능
하다. - whisper함수는 protected이므로 public함수에서
접근이 불가능
하다.
- giveSpeech 함수는 확장 함수로 public이 기본이므로 internal TalkativeButton 수신 타입을
내부(inner) 클래스와 중첩(nested) 클래스 : 기본은 중첩
자바에서는 static 키워드를 사용하지 않고 클래스 내부에 클래스를 선언하면 기본적으로 내부(inner) 클래스로 선언된다. 내부 클래스는 외부 클래스를 모르게 참조하고 있어 만약 직렬화 시 원하는대로 작동되지 않을 수가 있다.
코틀린에서는 자바와는 다르게 내부에 클래스를 선언하게 되면 중첩(nested)클래스로 선언된다. 자바에서 static으로 선언한 내부 클래스와 똑같이 말이다. 만약 내부 클래스로 선언하려면 inner
변경자를 붙여야 하며 내부에서 외부 클래스를 접근하려면 this@클래스명
으로 접근해야 한다.
1 | class Outer { |
봉인된 클래스 : sealed
인터페이스로 선언한 클래스를 상속받은 클래스를 when
구문으로 타입 검사를 할 경우 항상 else
구문이 강제되어야 한다. 만약 인터페이스를 상속한 클래스를 해당 when구문에 추가하지 않는다면 else구문이 실행되므로 원하지 않는 에러가 발생할 수 있다. 코틀린에서는 이런 문제점을 해결하기 위해 sealed
라는 변경자를 지원한다. 이 sealed 변경자는 클래스 계층 정의 시 계층 확장을 제한에 둔다.
1 | // interface로 상속받은 클래스 별 실행 |
sealed 클래스 내부에 선언한 클래스들은 Expr 클래스를 상속받고 있어 when 구문에서 타입 검사가 이뤄지며 코틀린에서는 만약 Expr클래스를 상속받은 다른 클래스가 생기면 컴파일 에러로 사용자에게 알려준다. 또한 sealed 클래스는 상속이 가능하므로 open 클래스이며 기본으로 open 변경자
를 갖고 있다.
출처 : Kotlin in Acation