Kotlin/Kotlin Language

[Kotlin] companion object

chattymin 2023. 2. 11. 10:10
728x90
반응형

코틀린에는 static이 없다.

자바를 쓰던 사람들에게는 놀라운 소리일 것이다. 나 또한 그랬고. 그럼 어떻게 static을 쓸까?

companion object를 활용해서 static을 사용한다. 

 

companion object의 블럭 내부에 값을 넣어준다면 해당 값들이 static처럼 사용된다.

class Test {
    companion object{
        var age = 10
        val number = 20
        const val num = 30
        fun sayHi() = println("hi")
    }
}

이와 같이 사용할 수 있다.

각각의 값들은 static으로 선언되고, 어디에서나 사용할 수 있다. 일종의 싱글톤이 되는 것이다.

그렇기 때문에 하나의 클래스에는 하나의 companion object만이 생성될 수 있다. 두개 만들려고 하면 에러난다. 

 

그럼 여기서 궁금한게 생길수도 있다.

val number = 20과 const val num = 30

이 두개는 뭐가 다른걸까?

val을 사용해서 수정이 불가능 하다는 것도 똑같고, companion object 내부에 있으니까 static처럼 사용한다는 것도 똑같다.

 

이는 해당 값이 결정되는 시기에 따른 차이점이 존재한다

먼저 val의 경우 내부 값을 초기화 한 후 값이 고정된다. 즉, "런타임"에 값이 결정된다는 것이다.

그러므로 val을 선언할때마다 값이 변할 수 있으므로 불완전한 불변성이다.

 

하지만 const의 경우 "컴파일"시에 값이 결정된다. 그러므로 const는 반드시 companinon object 내부에만 넣어야한다.

언제쓰든 항상 같은 값이므로 완전한 불변성이다.

 

말로만 들어서는 뭔 소린지 헷갈릴텐데 아래 예시와 같이 보자.

class Test {
    companion object{
        var age = 10
        val number = Random().nextInt(5)
        const val aee = 20
        fun sayHi() = println("hi")
    }
}

val number의 경우 Random.nextInt(5)라는 값을 가지고 있다. 그렇기 때문에 런타임시에 값이 정해지고, 수정불가능 해지는 것이다.

하지만 const val의 경우 이러한 사용이 불가능하다. const val은 반드시 Int, String 등과 같은 primitive type만 받을 수 있다.

 

정리하자면

val : primitive type + refernece type 가능 / 런타임시에 할당

const val  : primitive type가능 / 컴파일시에 할당

 

 

내부 function의 경우 그냥 부르면 된다.

fun main(){
	Test.sayHi() // hi
    Test.Companion.sayHi() // hi
    // 둘다 똑 같 다
}

 

 

 

또다른 재미있는 점은 companion object는 엄연히 "객체"다. 그렇기 때문에 이름을 붙일수도 있다.

class Test {
    companion object person{
        var age = 10
        val number = Random().nextInt(5)
        const val height = 180
        fun sayHi() = println("hi")
    }
}

이렇게 되면 내부 값을 불러올때는 어떻게 해야할까?

fun main(){
    println(Test.age)
    println(Test.person.age)
    println(Test.number)
    println(Test.person.number)
    Test.sayHi()
    Test.person.sayHi()
    //Test.Companion.sayHi() // Err
}

붙인 이름을 사용해도 되고, 사용하지 않아도 된다. 단, 이때 이전처럼 Companion을 붙이면 에러가 난다.

 

난 솔직히 이름을 왜 붙이는지 모르겠다. 굳이....?

뭐 일단 이름을 붙일수 있다 라는 것만 알고 간다.

 

 

 

지금까지 글만 읽으면 자바의 static이 코틀린의 companion object구나~ 라고 생각할 수있다. 그러나 companion object는 객체이다. 그렇기 때문에 더 많은 일을 할 수 있다. 자세한 내용은 어려워서 아직 완전히 이해하지 못했다. 추후에 이해한다면 추가로 글을 작성해보겠다. 

 

728x90
반응형