Kotlin :: 클래스, 객체, 인터페이스 2

클래스, 객체, 인터페이스 1에 이어 클래스, 객체, 인터페이스2 를 시작한다.

클래스 선언

코틀린에서는 생성자를 주 생성자(primary constructor)부 생성자(secondary constructor)로 나눈다. 주 생성자는 단 한번만 선언할 수 있으며 부 생성자를 여럿 선언할 수도 있다.

클래스 초기화: 주 생성자와 초기화 블럭

코틀린에서 제공하는 주 생성자는 클래서 선언과 동시에 이뤄진다.

1
class User(val nickname: String)

보통 클래스의 모든 선언은 중괄호({}) 사이에 들어가지만 코틀린의 주 생성자는 클래스 이름 뒤에 괄호로 선언한다. 주 생성자는 생성자 파라미터를 지정하고 그 생성자 파라미터에 의해 초기화되는 프로퍼티를 정의하는 두 가지 목적에 쓰인다.

1
2
3
4
5
6
7
8
9
10
11
class User constructor(_nickname: String) {
val nickname: String
init {
nickname = _nickname
}
}

// constructor, init 생략 가능
class User(_nickname: String) {
val nickname = _nickname
}
  • constrcutor 키워드는 주 생성자나 부 생성자를 정의할 때 사용한다.
  • init 키워드는 초기화 블록을 시작한다.

생성자에는 디폴트 파라미터를 설정할 수 있으며 객체 생성시 이름도 지정 가능하다. 또한 모든 생성자 파라미터에 디폴트 값을 지정하면 컴파일러가 자동으로 파라미터가 없는 생성자를 만들어 주기도 한다.

클래스를 상속할 땐 꼭 부모 클래스의 주 생성자를 호출해야 한다. 아래와 같이 말이다.

1
2
open class User(val nickname: String) { ... }
class TwitterUser(nickname: String): User(nickname) { ... }

위와 같이 클래스를 상속하게 되면 주 생성자를 호출해야 하므로 상속받는 클래스명 뒤에 괄호를 사용해야 한다. 하지만 인터페이스는 생성자가 없으므로(실제로는 클래스가 private) 인터페이스를 상속받을 땐 괄호를 사용하지 않고 선언할 수 있다. 그러므로 어떤 클래스가 2개의 클래스를 상속받는 데 하나는 괄호가 있고 하나는 괄호가 없다면 괄호 있는 이름이 클래스이며 괄호 없는 이름이 인터페이스로 구분이 쉽게 가능하다.

인터페이스 프로퍼티 구현

코틀린에서는 인터페이스에 추상 프로퍼티 선언을 넣을 수 있다. 또한 프로퍼티의 구현도 가능하여 아래와 같이 작성할 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
interface User {
val nickname: String
}

class PrivateUser(override val nickname: String) : User
class SubscribingUser(val email: String) : User(
override val nickname: String
get() = email.substringBefore('@')
}
class FacebookUser(val accountId: Int): User {
override val nickname = getFacebookName(accoundId)
}
  • PrivateUser은 주 생성자 안에 프로퍼티를 직접 선언하는 방법을 선택하였다.
  • SubscribingUser는 nickname을 호출할 때마다 주 생성자에서 입력받은 email을 계산하여 반환한다.
  • FacebookUser는 초기화 구문으로 nickname에 getFacebookName 함수로 이름을 초기화 한다.

게터와 세터에서 뒷받침하는 필드에 접근

데이터 값이 변경 됨에 따라 어떤 값으로 변경했는지 알고 싶을 때 기존 값과 새로운 값의 로그를 작성하는데 이 로직을 세터에서 할 수 있도록 작성이 가능하다.

1
2
3
4
5
6
7
8
9
class User(val name: String) {
var address: String = "unspecified"
set(value: String) {
println("""
Address was changed for $name:
"$field" -> "$value".""".trimIndent())
field = value
}
}

프로퍼티에서 원래의 값을 접근할 땐 field식별자를 사용하여 접근이 가능하다.

접근자의 가시성 변경

접근자의 가시성은 기본적으로 프로퍼티 가시성과 같으며 private으로 작성 시 외부에서는 해당 접근자에 접근을 못하지만 내부에서는 할 수 있다.

1
2
3
4
5
6
7
class LengthCounter {
var counter: Int = 0
private set
fun addWord(word: String) {
counter += word.length
}
}

출처 : Kotlin in Acation

댓글

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×