companion object 는 클래스이자 객체이다.
코틀린에서 object 키워드는 클래스 선언이자 동시에 객체 초기화를 동시에 하도록 동작한다.
object expression 으로 동작하는 경우 무명 클래스를 선언하고 객체화하는 것과 같고, companion object 처럼 declration 으로 동작하는 경우에도 마찬가지이다.
이를 확인해보기 위해 아래와 같이 선언해보자.
class NamedCompanion {
companion object Foo {
}
}
그리고 간단하게 이를 확인하기 위해, 아래 테스트를 만들어보면 동작함을 알 수 있다.
만약, companion object가 아닌 일반 클래스를 아래와 같은 방식으로 작성하게 되면, 동작하지 않는다.
foo 는 객체로 취급되지만, NamedCompanion.Foo 는 클래스(타입)으로 취급된다.
@Test
fun namedCompanionTest() {
val foo = NamedCompanion.Foo
Assertions.assertThat(foo is NamedCompanion.Foo).isTrue()
}
companion object 는 클래스가 초기화 될 때 로드가 된다. java 의 static 멤버나 메서드와 같은 방식으로 동작하는 것이다.
여기서 java의 static class와 혼동하면 안된다. 물론, nested class 중 static class 또한 초기화 되는 시점은 companion object와 같으나, static class 는 말 그대로 class 이기 때문에 인스턴스화가 필요하다. 오히려, 코틀린의 nested class (inner 키워드가 붙지 않은) 가 static class와 가깝다.
아래는 companion object 의 예이다. Outer class의 인스턴스화가 필요하지 않고, static 변수, 메서드 처럼 동작하기 때문에, outer class 의 인스턴스 변수에 접근할 수 없다.
class CompanionOuter(private val greet: String) {
private fun outerHello(): String {
return greet
}
companion object Foo {
fun hello(): String {
return CompanionCls("hello").outerHello();
}
}
}
// 인스턴스화가 필요없다. 그 자체로 클래스이자 객체이다.
val actual = CompanionOuter.Foo.hello();
그렇다면, companion object 가 자바의 static 변수나 메서드처럼 동작한다면, 코틀린의 nested class 는 이를 접근할 수 있을까? → 가능하다
class DefaultNested {
companion object {
private val companionGreet = "companionHello"
}
// nested class
class Foo {
fun companionHello(): String {
// outer class의 companion object에 접근 가능
return companionGreet
}
}
}
val greeting = DefaultNested.Foo().companionHello(); // companionHello
이는 암기할 필요가 없는 부분인데, static 과 인스턴스 멤버가 언제, 어디에 로드 되는지 알면 왜 참조가 어떤 방향은 가능하고, 어떤 방향은 불가능한지 쉽게 알 수 있다.
static 의 경우, JVM의 메서드 영역에 저장이되고 이 메모리 영역은 class 단위로 공유가 된다.
하지만, 객체는 힙 영역에 로드가 되므로 객체가 생성되기 전까지 JVM 메모리 상에 없다. 따라서 메서드 영역의 static → 인스턴스 멤버 영역을 참조할 수 없으나, 그 반대는 가능한 것이다.
'자바와 코틀린' 카테고리의 다른 글
코루틴 - 중단함수 (0) | 2024.09.17 |
---|---|
코루틴 - 구조화된 동시성 (2) | 2024.09.17 |
코루틴 - 코루틴 빌더와 Job (0) | 2024.09.17 |
코루틴 - CoroutineDispatcher (0) | 2024.09.17 |
프로세스와 스레드(운영체제 기본) (0) | 2024.07.29 |