[Kotlin] 클래스, 객체, 인터페이스(4)

sw·2022년 4월 3일
0

1. object : 클래스 선언과 인스턴스 생성

  • object 키워드를 통해 클래스를 정의하는 동시에 객체를 생성한다.

  • 싱글턴을 정의하는 방법 중 하나이다.

  • companion object는 인스턴스 메소드는 아니지만 어떤 클래스와 관련 있는 메소드와 팩토리 메소드를 담을 때 쓰인다. compainon object 메소드에 접근할 때는 companion object가 포함된 클래스의 이름을 사용할 수 있다.

  • 객체 식은 자바의 anonymous inner class 대신 쓰인다.

  • lazy하게 초기화 된다.



2. object declaration : 싱글턴을 쉽게 만들기

  • Kotlin은 object declaration 기능을 통해 싱글턴을 언어에서 기본 지원한다.
    object declaration = 클래스 선언 + 그 클래스에 속한 단일 인스턴스의 선언

  • object declaration에 생성자 정의는 필요 없다. object declaration이 있는 위치에서 생성자 호출 없이 즉시 만들어지기 때문이다.

  • object declaration도 클래스나 인터페이스를 상속할 수 있다.

object Payroll {
    val allEmployees = arrayListOf<Person>()
    fun calculateSalary() {...}
}

Payroll.allEmployees.add(Person(...))
Payroll.calculateSalary()
  • 클래스 안에서 객체를 선언할 수 있다. 마찬가지로 이 객체의 인스턴스는 1개다.
data class Person(val name: String) {
    object NameComparator : Comparator<Person> {
        override fun compare(p1: Person, p2: Person): Int =
            p1.name.compareTo(p2.name)
    }
}

>>> val persons = listOf(Person("Bob"), Person("Alice"))
>>> println(persons.sortedWith(Person.NameComparator))



3. companion object : 팩토리 메소드와 정적 멤버가 들어갈 장소

  • 어떤 클래스의 모든 인스턴스가 공유하는 객체를 만들고 싶을 때 사용하며, 클래스당 한 개만 가질 수 있다.

  • 자신을 둘러싼 클래스의 모든 private 멤버에 접근할 수 있다.

  • companion object의 프로퍼티나 메소드에 접근하려면 그 companion object가 정의된 클래스 이름을 사용한다.

  • 이름을 생략할 수 있고 생략하게 되면 Companion이란 이름으로 접근할 수 있다.

class Obj {
    companion object{
        fun hi() = println("HI")
    }
}
>>> Obj.hi()
>>> Obj.Companion.hi()
HI
HI
// Obj.멤버는 Obj.Companion.멤버의 축약표현!!!!

class Person(val name: String) {
    companion object Loader {
        fun fromJSON(jsonText: String) : Person { ... }
    }
}
>>> person = Person.Loader.fromJSON("{name: 'Dmitry'}")
>>> person.name
Dmitry

>>> person = Person.fromJSON("{name: 'Brent'}")
>>> person.name
Brent
  • 팩토리 패턴을 구현하기 가장 적합한 위치이다.
class User private constructor(val nickname: String) {
    companion object {
        fun newSubscribingUser(email: String) = User(email.substringBefore('@'))
        fun newFacebookUser(accountId: Int) = User(getFacebookName(accountId))
    }
}
  • 인터페이스 구현이 가능하다.
interface JSONFactory<T> {
    fun fromJSON(jsonText: String): T
}

class Person(val name: String) {
    companion object : JSONFactory<Person> {
        override fun fromJSON(jsonText: String): Person {...}
    }
}
  • companion object는 객체이기 때문에 변수에 할당이 가능하다.
class Obj {
    companion object{
        fun hi() = println("HI")
    }
}

>>> val obj = Obj.Companion
>>> obj.hi()
HI

>>> val obj2 = Obj
>>> obj2.hi()
HI
  • 자바에서 사용하기 위해 코틀린 클래스의 멤버를 static하게 만들려면 @JvmStatic 애노테이션을 코틀린 멤버에 붙이면 된다. static field가 필요하면 @JvmField 애노테이션을 붙인다.


4. 객체 표현식: 익명 내부 클래스를 다른 방식으로 작성

  • 객체 선언과 달리 익명 객체는 싱글턴이 아니다. 객체 식이 쓰일 때마다 새로운 인스턴스가 생성된다.
profile
끄적끄적

0개의 댓글