728x90

객체 지향 언어에서는 객체를 생성하기 위해서는 먼저 클래스를 선언하고, 해당 클래스로부터 객체를 생성한다.

하지만, 코틀린에서는 이런 과정을 거치지 않고도 객체를 생성할 수 있다.

object 키워드를 사용하면, 클래스가 아니라 객체 그 자체, 인스턴스가 된다.


코틀린에는 static keyword가 없고 object 키워드를 통해
- 싱글턴을 정의하는 방법
- 동반객체 companion object를 이용한 팩토리 메서드 구현
- 무명클래스(익명 클래스)의 선언
를 한다.


예제1

fun main(){
    // Person은 그 자체로 하나의 객체이기 때문에, 바로 .을 찍어 프로퍼티나 메서드에 접근할 수 있다.
    Person.name = "홍길동"
    Person.age = 30
    println("이름 : ${Person.name}, 나이 : ${Person.age}")
}

// object 는 subclass 의 명시적인 선언 없이 객체 생성
object Person {
    var name: String = ""
    var age: Int = 0
}
 


예제2

- object 키워드는 어떤 객체가 반드시 하나만 존재해야 할 때, 즉 싱글톤 패턴에 활용할 수 있다.

// 예제 2.1

fun main(args: Array<String>) {
    Singleton.printVarName()

    println("\nSingleton variableName Change")
    Singleton.variableName = "강감찬"
    var a = A()
}

object Singleton{
    init {
        println("Singleton class invoked.")
    }
    var variableName = "홍길동"
    fun printVarName(){
        println("변수명 : $variableName ")
    }
}

class A {
    init {
        println("Class init method. Singleton variableName property : ${Singleton.variableName}")
        Singleton.printVarName()
    }
}

// 예제 2.2
fun main(args: Array<String>) {
    var a = A()
    a.printVarName()

    println()
    Singleton.printVarName()
}

open class A {
    open fun printVarName() {
        println("I am in class printVarName")
    }

    init {
        println("I am in init of A")
    }
}

object Singleton : A() {
    init {
        println("Singleton class invoked.")
    }

    var variableName = "홍길동"
    override fun printVarName() {
        println(variableName)
    }
}



예제3. companion object

- 동반 객체(companion object)는 최상위 수준에서는 사용할 수 없고 클래스 내부에 정의하여 사용한다.

  동반 객체는 클래스 내부에 정의된 객체 선언이라고 할 수 있다.

  하나의 클래스에는 하나의 동반 객체만 포함될 수 있다.

- 동반 객체를 포함하는 클래스 내부에서는 동반 객체의 속성이나 함수를 자신의 속성이나 함수인 것처럼 인식하므로 동반 객체의 이름을 지정하지 않고 사용할 수 있다.

- 카 판매 버튼을 클릭할 때마다 카운트가 증가되는 함수라고 생각하면 된다.

- companion object 가 서로 다른 객체(아우디, 그랜저)의 카운트 총합을 자동 합산한다.

fun main(args: Array<String>){
    var car1 = CarSales("아우디")
    var car2 = CarSales("그랜저")

    car1.sales()
    car1.sales()
    car1.sales()
    car1.sales()

    car2.sales()
    car2.sales()

    println("${car1.name} : ${car1.count}")
    println("${car2.name} : ${car2.count}")
    println("총계 : ${CarSales.total}")
 
}

// object 는 subclass 의 명시적인 선언 없이 객체 생성

class CarSales(val name: String){
    // 코틀린에는 정적(static) 변수 혹은 메소드가 없고,
    // 대신 패키지 내에 함수를 선언하여 사용할 수 있다.
    companion object {
        var total = 0
    }

    var count = 0
    fun sales(){
        total++
        count++
    }
}


예제4

fun main(args: Array<String>){
    var first = MyHtml.generateHtmlObject("first")
    first.setColumnHeaders("1열","2열","3열")
    //println("first.generateTable() => ${first.generateTable()}")

    val second = MyHtml.generateHtmlObject("second", 5,5)
    second.setColumnHeaders("월","화","수","목","금")

    val third = MyHtml.generateHtmlObject("third",2,7)
    third.setColumnHeaders("적색","녹색","노랑","파랑","보라","검정","주황")

    println("생성된 table 개수 : ${MyRecord.showTableCount()}")
    for( (k,v) in MyRecord.showTable()) {
        println("\n <!-- $k table (${v.row} x ${v.col}) -->")
        println(v.generateTable())
        println()
    }
}

object MyRecord {
    private var _count = 0
    private val _tables = hashMapOf<String,MyHtml>()

    fun gen(table: MyHtml){
        _tables.put(table.name, table)
        _count++
    }
    fun showTableCount() = _count
    fun showTable(): Map<String,MyHtml> = _tables
}

class MyHtml {
    val name: String
    val row: Int
    val col: Int
    private val HEAD = "<table border='1' cell-spacing='10' cell-padding='10'"
    private val TAIL = "</table>"
    private lateinit var comment: String
    private val tableColumns = ArrayList<String>()

    private constructor(_name: String, row: Int, col: Int ){
        this.name = _name
        this.row = row
        this.col = col
    }

    fun setColumnHeaders(vararg colNames: String){
        this.tableColumns.addAll(colNames)
    }

    companion object _GenTable {
        fun generateHtmlObject(_name: String, row: Int = 2, col: Int = 3): MyHtml {
            val mh = MyHtml(_name, row, col)
            mh.comment = "<!-- auto-generator table by MyHtml v1.0 -->"
            // 테이블 객체 기록
            MyRecord.gen(mh)
            return mh
        }
    }

    private inner class Tr {
        val rowHtml = """
            |<tr>
            | ${"<td>-</td>".repeat(col)}
            |</tr>${"\n"}
        """.trimMargin()
    }

    private inner class Th(val wpx: Int = 40) {
        val headers = tableColumns.map {
            "<th width='$wpx'> $it </th>"
        }
        val rowHtml = """
            |<tr>
            | ${headers.joinToString("")}
            |</tr>
        """.trimMargin()
    }

    // 테이블 생성 실행
    fun generateTable() =
        """
                |$comment
                |$HEAD
                |${Th().rowHtml}
                |${Tr().rowHtml.repeat(row)}
                |$TAIL
            """.trimMargin()
}


블로그 이미지

Link2Me

,