내용 보기

작성자

관리자 (IP : 172.17.0.1)

날짜

2020-07-09 06:48

제목

[Kotlin] 코틀린 기초 08 - Object 클래스


  • Object 클래스

object 예약어는 익명 클래스를 정의할 때 사용한다. 클래스 선언 때 class 예약어를 작성하지 않고 object { } 형태로 선언한다. 이렇게 선언한 object클래스는 클래스명이 없지만 선언과 동 시 에객체가 생성된다.

// object 클래스

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Test {
    private var _no: Int = 0;
 
    val myObjInner = object {
        val name: String = "test";
        fun innerFun() {
            println("myObjInner -> innerFun");
            _no ++;
        }
    }
 
    fun outerFun() {
        println("myObjInner name : ${myObjInner.name}");    // 에러 발생
        myObjInner.innerFun();                              // 에러 발생
    }
}
 
 
val obj: Test = Test();
obj.outerFun();
cs


object클래스의 맴버를 외부에서 접근할 때는 object클래스 선언때 private접근자를 추가해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Test {
    private var _no: Int = 0;
    private val myObjInner = object {
        val name: String = "test";
        fun innerFun() {
            println("myObjInner -> innerFun");
            _no ++;
        }
    }
 
    fun outerFun() {
        println("myObjInner name : ${myObjInner.name}");
        myObjInner.innerFun();
    }
}
 
val obj: Test = Test();
obj.outerFun();
cs

실행결과

myObjInner name : test

myObjInner -> innerFun

private접근자로 선언해야 외부에서 이용할 수 있는 이유는 다음과 같다.
object클래스인 myObjInner클래스는 타입이 없기에 Any타입으로 인식된다.
Any타입이어서  결국 프로퍼티 및 메서드는 없기에 외부에서 맴버 접근시 오류가 발생된다.
private접근자로 선언하면 내부에서만 사용하겠다는 의미로 object타입 그대로 반환되어 맴버들이 그대로 노출되어 접근이 가능하다.

  • object 선언

object와 { } 사이에 클래스명을 명시해 선언할 수도 있다. 클래스명이 명시된 object클래스는 선언과 동시에 클래스명과 같은 이름의 객체까지 생성된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class NormalClass {
    fun myFun() {
        println("NormalClass -> myFun");
    }
}
 
object ObjectClass {
    fun myFun() {
        println("ObjectClass -> myFun");
    }
}
 
val obj1: NormalClass = NormalClass();
val obj2: ObjectClass = ObjectClass();      // 오류 발생
 
obj1.myFun();
ObjectClass.myFun();
cs

실행 결과

NormalClass -> myFun

ObjectClass -> myFun

클래스명이 명시된 object 클래스인 ObjectClass는 선언과 동시에 해당 객체가 생성되었기 때문에 바로 해당 클래스 이름으로 해당 맴버에 접근이

가능하다. C#의 static처럼 사용이 가능하다.

하지만

1
val obj2: ObjectClass = ObjectClass();
cs

처럼 object클래스를 직접 객체 생성시에는 오류가 발생한다.


  • companion 예약어

클래스명이 명시된 object클래스는 특정 클래스 안에 작성할 수도 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Outer {
    object NestedClass {
        val no: Int = 0;
        fun myFun() {
            println("NestedClass -> myFun");
        }
    }
}
 
val obj:Outer = Outer();
obj.NestedClass.myFun();    // 오류 발생
 
Outer.NestedClass.myFun();
cs

실행결과

NestedClass -> myFun


Outer클래스 안에 object NestedClass클래스가
선언되어 있고 NestedClass의 맴버에 접근할때는 바로

1
Outer.NestedClass.myFun();
cs

식으로 접근이 가능하다.

1
2
val obj:Outer = Outer();
obj.NestedClass.myFun();
cs

위 식의 접근은 오류 발생한다.

Outer클래스에서 NestedClass내부 맴버에 위 같은 식으로 접근할 수는 있는데 항상 부모 클래스인 Outer을 통해 접근할 수만 있다.
이때 companion예약어를 같이 사용하면 object클래스의 맴버를 object클래스명을 사용하지 않고 바로 접근할 수 있다.

1
2
3
4
5
6
7
8
9
10
class Outer {
    companion object NestedClass {
        val no: Int = 0;
        fun myFun() {
            println("NestedClass -> myFun");
        }
    }
}
 
Outer.myFun();
cs

실행결과

NestedClass -> myFun

위 처럼 companion object를 이용하면 static같은 효과를 낼 수 있다.

출처1

출처2