객체 지향 언어에서는 객체를 생성하기 위해서는 먼저 클래스를 선언하고, 해당 클래스로부터 객체를 생성한다.
하지만, 코틀린에서는 이런 과정을 거치지 않고도 객체를 생성할 수 있다.
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() }
|