Rooted In Develop

Kotlin - DSL 본문

Back End/Kotlin

Kotlin - DSL

RootedIn 2023. 6. 24. 22:27

Kotlin 의 편의성 지원

Java Kotlin 특성
StringUtil.capitalize(s) s.capitalize() 확장 함수
1.to("one") 1 to "one" 중위 호출
set.add(2) set += 2 연산자 오버로딩
map.get("key") map["key"] get 메서드에 대한 관례
file.use({ f -> f.read() }) file.use { it.read() } 람다를 괄호 밖으로 빼내는 관례
sb.append("yes")
sb.append("no")
with (sb) {
  append("yes")
  append("no")
}
수신 객체 지정 람다

DSL

외부 DSL : SQL

SELECT Country.name, COUNT(Customer.id)
  FROM Country
  JOIN Customer ON Country.id = Customer.country_id
  GROUP BY Country.name
  ORDER BY COUNT(Customer.id) DESC
  LIMIT 1

내부 DSL : Exposed

(Country join Customer)
  .slice(Country.name, jCount(Customer.id))
  .selectAll()
  .groupBy(Country.name)
  .orderBy(Count(Customer.id), isAsc = false)
  .limit(1)

수신 객체 지정 람다

// 람다를 인자로 받는 함수
fun buildString(builderAction: (StringBuilder) -> Unit) : String {
  val sb = StringBuilder()
  builderAction(sb)
  return sb.toString()
}
>>> val s = buildString {
  it.append("Hello, ")
  it.append("World!")
}

// 수신 객체 지정 람다를 사용해 재정의
fun buildString(builderAction: StringBuilder.() -> Unit) : String {
  val sb = StringBuilder()
  sb.builderAction()
  return sb.toString()
}
>>> val s = buildString {
  this.append("Hello, ")
  append("World!")
}
val appendExcl : StringBuilder.() -> Unit = { this.append("!") }
>>> val stringBuilder = StringBuilder("Hi")
>>> stringBuilder.appendExcl() // appendExcl 를 확장 함수처럼 사용 가능
>>> println(stringBuilder)
Hi!
>>> println(buildString(appendExcl)) // appendExcl 를 인자로 넘길 수 있음
!

HTML 빌더 구현

open class Tag(val name: String) {
  private val children = mutableListOf<Tag>()
  protected fun <T : Tag> doInit(child: T, init: T.() -> Unit) {
    child.init()
    childrene.add(child)
  }
  override fun toString() = "<$name>${children.joinToString("")}</$name>"
}
fun table(init: TABLE.() -> Unit) = TABLE().apply(init)
class TABLE : Tag("table") {
  fun tr(init: TR.() -> Unit) = doInit(TR(), init)
}
class TR : Tag("tr") {
  fun td(init: TD.() -> Unit) = doInit(TD(), init)
}
class TD : Tag("td")
fun createTable() =
  table {
    tr {
      td {
      }
    }
  }
>>> println(createTable())
<table><tr><td></td></tr></table>

invoke 관례 활용

class Greeter(val greeting: String) {
  operator fun invoke(name: String) {
    println("$greeting, $name!")
  }
}
>>> val bavarianGreeter = Greeter("Servus")
>>> bavarianGreeter("Dmitry") // bavarianGreeter.invoke("Dmitry")
Servus, Dmitry!

 

'Back End > Kotlin' 카테고리의 다른 글

Kotlin - annotation, reflection  (2) 2023.06.17
Kotlin - 제네릭스  (0) 2023.06.10
Kotlin - 고차 함수  (0) 2023.06.03
Kotlin - 연산자 오버로딩  (0) 2023.05.27
Kotlin - 타입 시스템  (0) 2023.05.06
Comments