본문 바로가기

Reading Record/이펙티브 코틀린

[이펙티브 코틀린] Item 33. 생성자 대신 팩토리 함수를 사용하라

아이템 33

생성자 대신 팩토리 함수를 사용하라

팩토리 함수의 장점

  • 생성자와 다르게 함수에 이름을 붙일 수 있다. 생성되는 방법과 아규먼트로 무엇이 필요한지 설명 가능하다.
  • 원하는 형태의 타입을 리턴할 수 있다. 인터페이스 뒤에 실제 객체의 구현을 숨길 때 유용하게 사용할 수 있다.
    • lisOf는 List인터페이스를 리턴한다. 실제로 리턴하는 객체는 플랫폼에 따라 다름
  • 호출될 때마다 새로운 객체를 만들 필요가 없다. 싱클턴 패턴처럼 객체를 하나만 생성하게 강제가능하다.
  • 아직 존재하지 않는 객체를 리턴할 수 있다. 앞으로 만들어질 객체를 사용하거나,프록시를 통해 만들어지는 객체를 사용할 수 있다.
  • Proxy.*newProxyInstance*()
  • 팩토리 함수는 인라인으로 만들 수 잇으며, 파라미터들을 reified로 만들수 있다
  • 생성자는 즉시 슈퍼클래스 또는 기본 생성자를 호출해야 하지만, 팩토리 함수를 사용하면 원하는 때에 호출가능

companion 객체 팩토리 함수


....
companion object {
   fun <T> of(vararg elements: T): MyLinkedList<T>? {
       ....
    }
}
...
  • companion 객체는 인터페이스,클래스 상속 가능
abstract class AbstractFooFactory() {
    abstract fun getFoo(): Foo

    fun start() {
        val foo = getFoo()
        println(foo+this.a)
    }
}

class DefaultFooActivity {
    companion object : AbstractFooFactory() {
        override fun getFoo(): Foo {
            return Foo("default")
        }

    }
}

data class Foo(private val text: String)

fun main() {
    DefaultFooActivity.start()
}
  • 추상클래스에 멤버변수가 포함될 시 companion object 상속시 멤버변수의 값을 채워 생성해야한다.

확장 팩토리 함수

interface Tool {
         companion object {}
}

fun Tool.Companion.createBigTool() : BigTool{
}
  • 팩토리 메서드를 만들어서 외부 라이브러리 확장 가능하다.
    • 다만 companion 객체가 선언되어 있어야한다.

톱레벨 팩토리 함수

  • 톱레벨 팩토리 함수를 이용하는 방법으로 listOf, setOf, mapOf가 가장 대표적인 예이다.
  • public 톱 레벨 함수는 모든곳에서 사용할 수 있으므로 ide가 제공하는 팁을 복잡하게 만드는 단점이 있다.

가짜 생성자

List(4) {"User$it"}

public inline fun <T> List(
size:Int,
init: (index:Int)->T
): List<T> = MutableList(size,init)
  • List는 인터페이스로 생성자를 가질 수 없지만, 가짜생성자를 통해 생성자를 가진것처럼 코드를 작성할 수 있다.
  • 가짜 생성자를 만드는 이유
    • 인터페이스를 위한 생성자를 만들고 싶을때
    • reified 타입 아규먼트를 갖게 하고 싶을때

팩토리 클래스의 메서드

  • 팩토리 클래스는 프로퍼티를 가질 수 있어, 이를 활용하면 다양한 종류로 최적화 가ㄴㅇ하고, 다양한 기능을 도입할 수 있다.
    • 이전에 만든 객체를 복제해서 객체를 생성하는 방법으로 객체 생성 속도를 높일 수 있다.
class SutudentsFactory{
     var nextId = 0
     fun next(name:String,surname:String = Student(nextId++,name,surname)
}