Kotlin

object, companion object

kakaroo 2022. 4. 15. 19:07
반응형

article logo

 

보통, 클래스로부터 생성되는 객체(서로 연관 있는 변수(속성) 들을 묶어놓은 데이터 덩어리)는 heap에 저장이 됩니다.

객체를 참조하는 변수는 stack 영역에 생성되어 그 객체의 주소를 가지고 있습니다.

 

val d1 = MyClass()   //MyClass 객체는 Heap 영역에 생성되고,  stack 영역에 변수 d1에 대한 메모리를 확보하고,  MyClass 의 주소를 갖게 됩니다.

 

 

  • Stack 영역은 컴파일 시점에 크기가 결정되는 영역 (매개변수, 지역변수 등),
  • Heap 영역은 런타임에 크기가 결정되는 영역이다. (동적할당, 객체 등)

 

object 키워드에 대해 알아 보겠습니다.

 

익명 객체

//object 키워드가 우변에 있을 경우 익명객체

//MyFunc 함수 호출시에 heap에 생성되었다가 함수가 완료되면 heap에서 완료됨
fun MyFunc() {
	val myObj = object {	
		val a = 10
		val b = 10
	}
	println(myObj.a)
}

 

싱글톤 객체

object SingleTon {
	val a : Int = 10
}

print(SingleTon.a)


//Java
public class SingleTon {
	private static SingleTon mSingleton;
    private int a = 10;
    public static SingleTon getInstance() { 
    	if (mSingleton == null) { 
        	mSingleton = new SingleTon(); 
        } 
        return mSingleton;
	}
}

힙 영역에 SingleTon이라는 객체는 하나만 생성됩니다.코틀린에서는 object 키워드만 붙이면 간단하게 싱글톤 패턴으로 된 객체를 생성할 수 있습니다. (Enum class도 동일함)

이렇게 선언된 객체는 프로그램 전체에서 공유할 수 있는 하나뿐인 객체 입니다.

 

object MyObject {
    const val a : Int = 10	//const 키워드는 top level이나 object에서만 붙일 수 있다.
}

class MyClass {
    val a : Int = 10
}
fun main(args: Array<String>) {

    val obj = MyObject
    println(obj.a)

    println(MyObject.a)
    println(MyClass.a)  //error ; 객체 생성 없이 바로 참조 불가능하다.
}

 

클래스 객체안에서 생성할 수도 있습니다.

* Person안에 object NameComparator를 만들었습니다. Person 인스턴스마다 객체 선언에 해당하는 인스턴스가 생성되는게 아니라, 단 하나의 객체선언 인스턴스만 생성됩니다.

그래서 Person.NameComparator으로 객체 선언된 NameComparator를 사용할 수 있습니다.

data class Person(val name: String) {
    object NameComparator : Comparator<Person> {
        override fun compare(p1: Person, p2: Person): Int = p1.name.compareTo(p2.name)
    }
}
fun main(args: Array<String>) {
    val persons = listOf(Person("하지마"), Person("변여름"), Person("나태웅"))
    println(persons.sortedWith(Person.NameComparator))

 


companion object (동반 객체)

Java나 C#과는 달리, 코틀린에는 static 멤버 변수나 함수가 없습니다. 만약 클래스 인스턴스없이 어떤 클래스 내부에 접근하고 싶다면, 클래스 내부에 객체를 선언할 때 companion 식별자를 붙인 object를 선언하면 됩니다.

 

아래 예에서 클래스내에 선언된 MyComp 라는 객체는 heap에 하나만 생성되어 여러 MyClass 객체들이 공유를 할 수 있게 됩니다.

//companion object
class MyClass {
    companion object MyComp {
        fun getValue(value: Int) {
            for(i in 1..value)
            	print(i)
        }
    }
}

MyClass1.MyComp.getValue(5)

companion object는 어떤 클래스의 모든 인스턴스가 공유하는 객체를 만들고 싶을 때 사용하며, 클래스당 한 개만 가질 수 있습니다

 

companion object 이름이 없는 경우 Companion 식별자를 사용할 수 있습니다. 이름이 있는 경우는 사용할 수 없습니다.

//companion object
class MyClass1{
    companion object {// MyComp {	//object 이름을 주석처리
        fun getValue(value: Int) {
            for(i in 1..value)
                println(i)
        }
    }
}
fun main(args: Array<String>) {

    val x = MyClass1.Companion.getValue(5)
    val y = MyClass1.getValue(5)	//Companion 는 굳이 안 붙여도 됩니다.

 

클래스 안에 private 로 선언된 프로퍼티나 메소드 혹은 생성자가 있을 경우 그 클래스 외부에서는 접근할 수 없습니다. 하지만 companion object 로 만들어진 동반 객체는 바깥쪽 클래스의 private 데이터에도 접근이 가능합니다. 그리고 이 동반객체를 호출하면 private로 선언된 데이터를 사용할 수 있습니다.

data class Person private constructor(val name: String) {
    companion object cObj {
        fun newPerson(cName: String) = Person(cName)
    }
}

fun main(args: Array<String>) {
    val person = Person.cObj.newPerson("가지마")
    println(person.name)
}

 

반응형

'Kotlin' 카테고리의 다른 글

SubsamplingScaleImageView  (0) 2022.04.23
Animation  (0) 2022.04.18
확장함수 (Extension Function)  (0) 2022.04.14
코루틴(Coroutine)  (0) 2022.04.03
BlogViewer (feat. JSoup Crawling)  (1) 2022.04.03