때로는 새로운 클래스를 명시 적으로 선언하지 않고 클래스를 약간 수정 한 객체를 만들어야합니다. 자바는
익명의 내부 클래스
로 처리합니다 . 코틀린은
객체 표현
과
객체 선언
으로이 개념을 약간 일반화합니다 .
오브젝트 식
어떤 타입 (또는 타입)으로부터 상속받은 익명의 클래스의 객체를 생성하기 위해 다음과 같이 작성합니다 :
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override 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
}
만일 우연히, "객체"을 필요로하고, 수퍼 타입이 없다면, 다음 코드를 사용할수 있습니다 :
fun foo() {
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
}
익명 객체는 로컬 및 개인 선언에서만 유형으로 사용할 수 있습니다. 익명 객체를 공용 함수의 반환 유형 또는 공용 속성의 유형으로 사용하는 경우 해당 함수 또는 속성의 실제 유형은 익명 객체의 선언 된 상위 유형이거나
Any
상위 유형을 선언하지 않은 경우입니다. 익명 객체에 추가 된 멤버는 액세스 할 수 없습니다.
class C {
// Private function, so the return type is the anonymous object type
private fun foo() = object {
val x: String = "x"
}
// Public function, so the return type is Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // Works
val x2 = publicFoo().x // ERROR: Unresolved reference 'x'
}
}
Java의 익명 내부 클래스와 마찬가지로 객체 표현식의 코드는 둘러싼 범위의 변수에 액세스 할 수 있습니다. (Java와 달리 최종 변수에만 국한되지 않습니다.)
fun countClicks(window: JComponent) {
var clickCount = 0
var enterCount = 0
window.addMouseListener(object : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
clickCount++
}
override fun mouseEntered(e: MouseEvent) {
enterCount++
}
})
// ...
}
오브젝트 선언
은 매우 유용한 패턴이며, 스칼라 (Scala) 이후의 코 틀린 (Kotlin)은 싱글 톤을 선언하기 쉽게 만든다.
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) {
// ...
}
val allDataProviders: Collection<DataProvider>
get() = // ...
}
이를
오브젝트 선언
이라고하며
오브젝트
키워드 다음에 항상 이름이 있습니다. 변수 선언과 마찬가지로 객체 선언은 표현식이 아니며 대입 문의 오른쪽에서 사용할 수 없습니다.객체를 참조하기 위해 이름을 직접 사용합니다.
DataProviderManager.registerDataProvider(...)
이러한 객체는 수퍼 유형을 가질 수 있습니다.
object DefaultListener : MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) {
// ...
}
}
참고
: 객체 선언은 로컬 일 수 없으며 (즉, 함수 내에 직접 중첩 될 수 있지만) 다른 객체 선언 또는 비 내부 클래스에 중첩 될 수 있습니다.
컴패니언 오브젝트
클래스 내의 객체 선언은
companion
키워드 로 표시 할 수 있습니다 .
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
클래스 이름을 한정자로 사용하여 컴패니언 개체의 멤버를 호출 할 수 있습니다.
val instance = MyClass.create()
컴패니언 개체의 이름은 생략 할 수 있습니다.이 경우 이름
Companion
이 사용됩니다.
class MyClass {
companion object {
}
}
val x = MyClass.Companion
컴패니언 객체의 멤버가 다른 언어의 정적 멤버처럼 보이더라도 런타임에는 여전히 실제 객체의 인스턴스 멤버이며 예를 들어 인터페이스를 구현할 수 있습니다.
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create(): MyClass = MyClass()
}
}
그러나
@JvmStatic
주석 을 사용하는 경우 JVM에서 컴패니언 객체의 멤버를 실제 정적 메서드 및 필드로 생성 할 수 있습니다 . 자세한 내용은
섹션을 참조하십시오.
오브젝트 식과 오브젝트 선언의 세만틱 차이
객체 표현과 객체 선언 사이에는 중요한 의미 상의 차이가 있습니다.
- 객체 표현은 사용되는 곳에서 즉시 실행되고 초기화 됩니다.
- 객체 선언은 처음 액세스 할 때 느리게 초기화 됩니다.
- 동등한 객체는 대응하는 클래스가로드 (해결)되었을 때에 초기화되어 Java static initializer의 시멘틱스에 일치합니다.
'프로그래밍 > kotlin' 카테고리의 다른 글
[코틀린 프로그래밍] Chapter.02 Java의 개발자를 위한 코틀린 필수 사항 (0) | 2021.12.27 |
---|---|
[코틀린 프로그래밍] Chapter.01 시작하기 (0) | 2021.12.27 |
코틀린 - Enum 클래스 (0) | 2021.07.13 |
코틀린 - 중첩 클래스 및 내부 클래스 (0) | 2021.07.13 |
코틀린 - 위임 (0) | 2021.07.13 |