때때로 새로운 클래스를 명시적으로 선언하지 않고 클래스를 조금 변경된 객체를 만들 필요가 있다.
Kotlin은 이런 케이스를 해결하기 위해 Object 식(expression)과 Object선언(declaration)을 지원한다.
Object 식
특정 타입을 상속받는 inner 클래스 객체를 만들 때는 다음과 같이 작성한다.
window.addMouserListener(object: MouseAdapter()){
override fun mouseClicked(e: MouseEvent){
//...
}
overrid fun mouseEntered(e: MouseEvent){
//...
}
})
상위 타입이 복수라면 콜론 뒤에 콤마로 구분한다.
open class A(x: Int) {
public open val y: Int = x
}
interface B { /\*...\*/ }
val ab: A = object : A(1), B {
override val y = 15
}
익명 객체가 inline으로 선언되어 있지 않고, 로컬 또는 private으로 선언되어있는 경우 타입으로 사용 가능하다.
익명 객체를 public 함수의 반환 type 또는 public으로 사용하는 경우, 해당 함수 또는 속성의 실제 타입은 익명 객체의 상위 타입이거나
상위 타입이 별도로 지정되어 있지 않는 경우는 Any가 된다.
익명 객체에 추가된 멤버에는 접근이 불가능 하다.
class C {
// Private function, 반환 타입은 익명 객체 타입
private fun foo() = object {
val x: String = "x"
}
// Public function, 반환 타입은 Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // Works
val x2 = publicFoo().x // ERROR: Unresolved reference 'x'
}
}
Object 선언
Kotlin은 object 키워드를 사용하여 싱글톤을 쉽게 구현할 수 있다.
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}
val allDataProviders: Collection<DataProvider>
get() = // ...
}
이러한 방식을 Object 선언이라고 지칭하며 항상 object 키워드 다음에 명칭을 한다.
참조 방식은 아래와 같이 Object의 이름을 직접적으로 사용한다.
DataProviderManager.registerDataProvider(...)
또한 슈퍼 타입을 가지는 것이 가능하다.
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
}
Companion Objects
클래스 내 Object 선언은 companion 키워드를 사용하여 적용할 수 있다.
class A {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
companion 객체의 멤버는 클래스의 이름을 한정자로 사용해서 호출할 수 있다.
val instance = MyClass.create()
만약 companion object의 객체 이름을 생략하면 Companion으로 대체할 수 있다.
class MyClass{
companion onject{
}
}
val x = MyClass.Companion
이렇게 놓고 보면 companion 객체의 멤버는 다른 언어에서의 static처럼 보일 수 있지만,
런타임에서는 실제 객체의 인스턴스 멤버로 생성된다.
(단, JVM에서는 @JvmStatic 어노테이션을 사용하여 companion 객체의 멤버를 정적 메소드나 필드로 사용 가능하다.)
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
Object 식과 선언의 차이점
- Object 식은 사용될 때 즉시 초기화가 된다.
- Object 선언은 최초 접근 시에 Lazy 하게 초기화된다.
- companion 객체는 대응하는 Class가 로드될 때 초기화된다.
'Kotlin' 카테고리의 다른 글
[Kotlin] 스레드와 코루틴 (0) | 2022.05.12 |
---|---|
[Kotlin] CoroutineBuilder (0) | 2022.05.12 |
[Kotlin] Delegated Properties (0) | 2022.03.23 |
[Kotlin] Delegation (0) | 2022.03.22 |
[Kotlin] 코틀린의 시퀀스(Sequence) (0) | 2022.01.24 |