코틀린 언어 정리 2-11

Object Expressions and Declarations

개요

object 키워드를 이용하여 클래스를 선언하고 객체를 생성하는 문법입니다.

클래스를 만들어 여러번 생성하지 않고 단 한번만 사용하는 경우 object expression(익명 클래스 및 객체)를 사용하면 불필요한 작업( 클래스 이름짓기, 클래스 선언, 클래스 소스코드 배치 등 )을 줄일 수 있어 유용합니다. 그리고 static 객체나 멤버 또는 singleton을 만들어야 할 때에는 object declaration을 사용합니다.(코틀린에는 static 키워드가 없습니다.)


object expressions

  • object expression으로 이름 없는 클래스를 만들 수 있으며 이 클래스는 선언 되자마자 객체를 생성합니다. 클래스 이름이 없으므로 1회성으로만 사용할 수 있습니다.

  • object를 사용하여 선언한 클래스는 선언 하자 마자 객체가 생성됩니다. 이 클래스는 일반 클래스와 다르게, 객체 생성을 위해 재참조 될 수 없습니다.


정리하면, 클래스를 필요한 곳에서 즉석에서 선언함과 동시에 객체를 생성 시킬 수 있는 문법이며 이름에서 알 수 있듯이, 표현식(expression)으로 사용할 수 있습니다. 일반 클래스는 객체 생성 시 클래스 이름을 통해 재사용(원하는 위치에서 원하는 만큼 객체를 생성)하는 것이 가능하지만 객체 표현식은 선언된 곳에서 1회성으로만 사용할 수 있습니다.


object declarations

  • object declaration은 object expression 에서 클래스 이름이 추가된 형식이며 표현식으로 사용할 수 없습니다.

  • object declaration은 전역(global) 또는 클래스 내에서 싱글톤 객체를 생성하는데 사용됩니다.

  • object를 사용하여 선언한 클래스는 선언 하자 마자 객체가 생성됩니다. 이 클래스는 일반 클래스와 다르게, 객체 생성을 위해 재참조 될 수 없습니다.

  • companion object는 object declaration과 유사한 선언 방법을 사용하며 static 멤버를 추가하는 개념으로 사용할 수 있습니다.


companion object

개요

companion object는 클래스 내부에 선언할 수 있습니다. 그리고 companion object 내부에 선언된 멤버는 데이터 저장 및 접근방법 등의 관점에서 자신을 포함한 클래스의 static 멤버처럼 취급 됩니다.


특징

  • companion object는 클래스 내에 1개만 선언할 수 있습니다.

  • companion object의 멤버는 companion object를 포함하는 클래스의 static 멤버처럼 접근할 수 있습니다.

  • companion object 선언 시 이름을 지정하거나 생략할 수 있습니다.

  • companion object 접근 시 이름을 지정하거나 생략할 수 있습니다.

  • companion object 선언 시 이름을 지정하지 않으면 기본적으로 "Companion"이라는 이름을 지정합니다.

  • 클래스 이름을 표현식으로 사용하는 경우 companion object를 리턴합니다.



지금까지 언급한 모든 유형 선언 예제

예제

class CompanionOuter(a: Int) {

   var a: Int = a


   // object expression inside class

   var obj = object {

       var a: Int = 0

       var b: String = "object expression"

   }


   // object declaration inside class

   object ObjectDeclaration {

       var a: Int = 10

       var b: String = "object declaration"

   }


   // companion object inside class

   companion object {

       var a: Int = 10

       var b: Int = 20

       var c: String = "companion object declaration"

   }


}


class NamedCompanionOuter(a: Int) {

   var a: Int = a


   // named companion object inside class

   companion object NamedCompanionInner {

       var a: Int = 10

       var b: Int = 20

       var c: String = "named companion object declaration"

   }

}


// object expression inside file

var obj = object {

   var a: Int = 0

   var b: String = "object expression"

}


// object declaration inside file

object ObjectDeclaration {

   var a: Int = 10

   var b: String = "object declaration"

}


// companion object inside file

//companion object { // compile error

//    var a: Int = 10

//    var b: Int = 20

//    var c: String = "companion object declaration"

//}


// named companion object inside file

//companion object NamedCompanionFile { // compile error

//    var a: Int = 10

//    var b: Int = 20

//    var c: String = "named companion object declaration"

//}


fun testDeclarationPosition() {

   // object expression inside file

   var obj = object {

       var a: Int = 0

       var b: String = "object expression"

   }


   // object declaration inside file

//    object ObjectDeclaration { // compile error

//        var a: Int = 10

//        var b: String = "object declaration"

//    }


   // companion object inside file

//    companion object { // compile error

//        var a: Int = 10

//        var b: Int = 20

//        var c: String = "companion object declaration"

//    }


   // named companion object inside file

//    companion object NamedCompanionFile { // compile error

//        var a: Int = 10

//        var b: Int = 20

//        var c: String = "named companion object declaration"

//    }

}


fun testCompanionOuter() {

   println("testCompanionOuter")

   println(CompanionOuter(1).a) // CompanionOuter의 멤버 a에 접근

//     println(CompanionOuter(10).b) // companion object의 멤버는 객체(instance)로 접근할 수 없습니다.

   println(CompanionOuter.a) // companion object의 멤버는 클래스 멤버인 것처럼 접근할 수 있습니다. 객체가 아닌 클래스로 접근하므로 클래스 멤버 이름과 companion object의 멤버 이름이 동일해도 이름 충돌이 발생하지 않는다.

   println(CompanionOuter.b) // companion object의 멤버는 클래스 멤버인 것처럼 접근할 수 있습니다.

   println(CompanionOuter.Companion.a) // companion object의 이름이 생략된 경우 이름이 Companion으로 지정됩니다. instance를 생성한 것이 아니므로 CompanionOuter의 멤버 a와 충돌하지 않는다.

   println(CompanionOuter.Companion.b)

   var companionObj = CompanionOuter // 클래스 이름을 표현식으로 사용하는 경우 companion object를 참조합니다.

   println(companionObj === CompanionOuter.Companion)

}



fun testNamedCompanionOuter() {

   println("testNamedCompanionOuter")

   println(NamedCompanionOuter(2).a) // 객체로 접근하는 경우 클래스(NamedCompanionOuter)의 멤버만 참조할 수 있습니다.

//    println(NamedCompanionOuter(2).b) // companion object의 멤버는 객체(instance)로 접근할 수 없습니다.

   println(NamedCompanionOuter.a) // companion object의 멤버와 클래스 멤버의 이름이 동일해도 충돌이 발생하지 않는다.

   println(NamedCompanionOuter.b)

//     println(NamedCompanionOuter.Companion.a) // companion object의 이름을 지정한 경우 Companion으로 접근 불가능합니다.

//     println(NamedCompanionOuter.Companion.b)

   println(NamedCompanionOuter.NamedCompanionInner.a)

   println(NamedCompanionOuter.NamedCompanionInner.b)

   var companionObj = NamedCompanionOuter // 클래스 이름을 표현식으로 사용하는 경우 companion object를 참조합니다.

   println(companionObj === NamedCompanionOuter.NamedCompanionInner)

}


//fun main(args: Array<String>) {

fun test() {

   testCompanionOuter()

   testNamedCompanionOuter()

}


+ Recent posts