[Kotlin] companion object와 java의 static 차이점?

resilient

·

2023. 8. 18. 22:16

728x90
반응형

최근 개인 프로젝트를 진행하던 도중 자바를 코틀린언어로 컨버팅을 한 경험이 있습니다.
 
코틀린이라는 언어에 대한 이해도가 부족한 상태였기 때문에 Intellij에서 제공하는 기능을 사용한 후, ChatGPT의 도움을 받아서 컨버팅을 진행했습니다.
 
바뀐 코드를 정독하던 도중 아래와 같이 바뀐 사실을 확인 할 수 있었습니다.
 
자바 코드

public class JavaConvert {
    private static final long MAX_SEAT = 100L;
}

 
코틀린 코드

public class MyClass {
    companion object {
        private const val MAX_SEAT = 100L
    }
}

 
자바에서 상수를 선언할 때 많이 사용하는 static final 키워드인데요.
(static에 대한 설명은 아래 포스팅을 참고하시면 좋을 것 같습니다.)

[자바/Java] Static 이란?

최근 싱글톤 패턴에 대해 공부하게 되었습니다. 싱글톤을 이해하기 위해서는 Static의 개념을 확실히 알고 있어야 한다는 블로그 글을 보았고, static에 대해서 이번 기회에 확실히 정리해보려고

resilient-923.tistory.com

 
java에서의 static이 kotlin으로 넘어왔을 때, companion object로 바뀐것을 알 수 있었습니다.
 
그럼 앞으로 static과 동일한 기능이 필요할 때, companion object를 사용하면 될까요? 이번 포스팅에서 알아 보겠습니다.
 

0. 코틀린에서 object 키워드란?

 
먼저 object키워드에 대해서 간단하게 짚고 넘어가려고 합니다.
 
위 두번째 예시처럼 object로 클래스를 정의하면, 싱글턴패턴이 적용되어 객체가 한번만 생성되도록 합니다.
 
자바에서 싱글턴 패턴을 적용한 클래스를 정의하고 사용하기 위해서는 꽤나 많은 형식적인 코드를 작성해야 했는데요.
 
코틀린에서는 object키워드를 사용하면 되죠. 또한 object는 익명객체를 생성할 때도 사용됩니다.
 

1. 그럼 companion object는 뭘까?

 
이제 companion object에 대해서 알아보겠습니다. 아래 코드를 보시죠.
 

class MyClass{
    companion object{
        val prop = "Companion object의 속성"
        fun method() = "Companion object의 메소드"
    }
}
fun main(args: Array<String>) {
    println(MyClass.prop)
    println(MyClass.method())
}

MyClass 클래스에 companion object 객체를 만들어서 2개의 멤버를 정의했습니다.
 
main() 함수를 보면 2개의 멤버에 접근하기 위해 MyClass.멤버 이렇게 사용하는데요.
 
사실 여기는 숨겨진 사실이 있습니다. 아래 처럼 companion이 생략되어 있는 것이죠. 축약해서 사용하는 것 뿐 입니다.

println(MyClass.companion.prop)
println(MyClass.companion.method())

 
정리해보면 companion object는 MyClass 클래스가 메모리에 적재되면서 동반(companion)되어 함께 생성되는 객체(object) 입니다. 클래스의 동반자 역할을 하게 되는 것이죠.
 

2. companion object는 static이 아니라객체입니다. 

 
위에서 말했듯이 companion object는 객체로 사용됩니다. 아래 코드를 보시죠.
 

class MyClass{
    companion object{
        val prop = "Companion object의 속성"
        fun method() = "Companion object의 메소드"
    }
}
fun main(args: Array<String>) {
    val comp1 = MyClass.companion  
    println(comp1.prop)
    println(comp1.method())
    
    val comp2 = MyClass
    println(comp2.prop)
    println(comp2.method())
}

위 코드에서 val comp1 = MyClass.companion 이부분을 보면 companion은 객체이기 때문에 변수에 할당할 수 있습니다.
객체를 변수에 할당한다? 이 부분은 나중에 다뤄보도록 하겠습니다.
 
변수에 할당하는 것은 static 키워드로 정의되어 있는 멤버는 불가능한 방법입니다. 차이점을 또 발견할 수 있죠.
 

3. companion object는 클래스에 하나만 있어야 합니다.

 
자바에서 static 멤버를 클래스에 아무데나 쓸 수 있었다면 코틀으로 변환해보면, 클래스에 하나의 companion object가 생성되고 그 안에 멤버들이 모이게 됩니다.
 

4. 정리

 
더 많은 static과의 차이점이 있겠지만 이정도만 봐도 코틀린에서 companion object가 자바의 static과 동일한 기능을 할 수는 있어도 동일하지는 않다는 점을 알 수 있습니다.
 
오히려 companion object가 staic과는 다르게 객체이기 때문에 훨씬 더 많은 기능을 할 수 있다는 점도 알 수 있었습니다.
 
감사합니다.

반응형