object & companion object

KEH·2023년 5월 2일
0
post-thumbnail

1️⃣ object

Kotlin에는 object 키워드가 존재합니다.
object 키워드는 object declarations(선언식) 방식과 object expressions(표현식) 방식으로 나눌 수 있습니다.


2️⃣ object declarations

Java에서도 Singleton 객체가 있듯, Kotlin에서도 Singleton 객체를 생성할 수 있는 방법이 있습니다.

Kotlin에서는 object declarations 방식을 통해 싱글톤 객체를 생성할 수 있습니다.

object SingletonEx {

	...

}
public class SingletonEx {
    private static SingletonEx INSTANCE = null;

    public static SingletonEx getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new SingletonEx();
        }

        return INSTANCE;
    }
}

두 코드는 싱글톤 객체를 생성하는 방법인데요, 위에는 Kotlin으로 작성한 것이고, 아래는 Java를 사용한 것입니다. Kotlin이 더욱 간단하게 싱글톤 객체를 만들 수 있습니다.

object declarations 방식의 특징은 다음과 같습니다.

1) thread safe

여러 스레드에서 동시에 동일한 object 객체를 사용하더라도 프로그램 실행에 아무런 문제가 발생하지 않습니다.

2) lazy initialization

말 그대로 '지연 초기화' 입니다. object 객체는 프로그램이 실행될 때 생성되는 것이 아니라 처음 사용되는 시점에 생성 됩니다.

3) ❌ 주생성자/부생성자 생성 불가 ❌

//주생성자
object SingletonEx constructor(_id: Int) {
    private val id: Int

    init {
        id = _id
    }
}
//부생성자
object SingletonEx {
    constructor(id: Int) {
    
    }

    constructor(id: Int, name: String) {

    }
}

다음과 같이 object 객체에서는 주생성자와 부생성자의 생성이 불가능 합니다.


3️⃣ object expressions

object expressions는 class로 선언되지 않은 익명 클래스 객체를 만듭니다. 사용하는 방법은 크게 두 가지가 있습니다.

1) 일시적으로 사용할 익명 클래스 객체 생성

private val objExpressions = object {
	val x: Int = 0
	val y: Int = 1

    fun add(): Int = x + y
}

objExpressions이란 객체를 클래스 이름 없이 object 키워드를 사용해 생성했습니다.

2) 특정 클래스나 인터페이스를 익명 클래스로 생성 및 구현 후 전달

binding.btn.setOnClickListener(object : View.OnClickListener {
	override fun onClick(p0: View?) {
    	...
	}
})

View.OnClickListener 인터페이스의 onClick 메서드를 구현한 익명 클래스를 object 키워드를 활용해 생성 후, View의 setOnClickListener 메서드의 매개변수로 전달합니다.

binding.root.setOnClickListener { 
	...   
}

kotlin에서는 위와 같이 람다식으로 더욱 간단하게 작성할 수 있습니다.


4️⃣ object declarations vs object expressions

두 방식은 초기화 되는 시점에서 차이가 있습니다.
object declarations의 경우 객체를 처음 사용하는 시점에서 생성되어 lazy initialization한 특징이 있지만, object expressions의 경우 즉시 초기화되어 생성됩니다.

또 object declarations는 싱글톤이기 때문에 한 번 생성된 객체를 재사용하는 반면, object expressions는 싱글톤이 아니기 때문에 사용이 될 때마다 객체가 즉시 생성됩니다.


5️⃣ Java static

Java에는 static 키워드가 존재합니다.
클래스 내부에 있는 변수나 메서드 앞에 static 키워드가 붙게 되면 '정적 변수', '정적 메서드', '클래스 변수', '클래스 메서드' 라고 합니다.

static 키워드를 통해 클래스의 인스턴스를 생성하지 않아도 해당 변수와 메서드를 사용할 수 있습니다.

public class Test1 {
    public static int num1 = 1;

    public static void sayHello() {
        System.out.println("Hello!");
    }
}
public class Test2 {
    public static void main(String[] args) {
        int num = Test1.num1;
        System.out.println("num: " + num);
        
        Test1.sayHello();
    }
}

6️⃣ companion object

Kotlin에는 Java의 static 개념이 없습니다. Java에 익숙한 분들이 처음 Kotlin을 접했을 때 당황스러울 수 있는 부분 중 하나인데요, Kotlin에서 static 개념을 대체할 수 있는 방법이 companion object를 사용하는 것입니다.

companion object는 클래스 내부에서 object 키워드를 활용해 객체를 선언하는 방법입니다. 주로 클래스 내부에서 싱글톤 패턴을 구현하기 위해 사용합니다.

class CompanionObjEx {
    companion object CompanionObj {
		val A: String = "A"
        val B: String = "B"
    }
}

class CompanionObjEx {
    companion object {
        val A: String = "A"
        val B: String = "B"
    }
}

companion object는 위와 같이 사용할 수 있고, companion object에 이름을 붙여도, 붙이지 안아도 사용 가능합니다. CompanionObj는 싱글톤 패턴이기 때문에 CompanionObjEx 인스턴스가 여러 개 생성되더라도 딱 하나만 생성됩니다.

CompanionObjEx.CompanionObj.A	//이름을 붙인 경우 -> "A" 출력
CompanionObjEx.Companion.A	//이름을 붙이지 않은 경우 -> "A" 출력
CompanionObjEx.A	//이름을 붙인 or 붙이지 않은 경우 -> "A" 출력

외부 클래스에서 companion object의 멤버 변수나 메서드를 사용할 경우 위와 같이 사용할 수 있습니다.

companion object가 Java의 static 개념을 대체할 수 있다고 해서 companion object가 static 개념과 같다고 할 수 없습니다. companion object는 static처럼 보이는 것일 뿐 엄연한 객체입니다.


7️⃣ object declarations vs companion object

object declarations와 companion object의 차이점은 어떤 것이 있을까요?

1. object declarations는 클래스 전체가 싱글톤 패턴이라면, companion object는 클래스 내부의 일부분만 싱글톤 패턴으로 구성됩니다.

2. object declarations는 초기화 시점이 클래스가 사용되는 시점이라면 companion object는 해당 클래스가 속해 있는 클래스가 사용될 때 초기화 됩니다.

profile
개발을 즐기고 잘하고 싶은 안드로이드 개발자입니다 :P

0개의 댓글