###実現したいこと:
"+" のマークを使用して、td { } 内に文字列を挿入したい。
###わからないこと:
unaryPlus() の{ }内にどのようなことを書けば、"+" が使えるようになるのかわかりません。
###問題のソースコード:
Kotlin
1open class Tag(val name: String) { 2 private val children = mutableListOf<Tag>() 3 4 protected fun <T : Tag> doInit(child: T, init: T.() -> Unit) { 5 child.init() 6 children.add(child) 7 } 8 9 override fun toString() = 10 "<$name>${children.joinToString("")}</$name>" 11} 12 13fun table(init: TABLE.() -> Unit) = TABLE().apply(init) 14 15class TABLE : Tag("table") { 16 fun tr(init: TR.() -> Unit) = doInit(TR(), init) 17} 18class TR : Tag("tr") { 19 fun td(init: TD.() -> Unit) = doInit(TD(), init) 20} 21class TD : Tag("td") 22 23fun createTable() = 24 table { 25 tr { 26 td {+"Hello" 27 } 28 } 29 } 30 31private operator fun String.unaryPlus() { 32 TODO("Not yet implemented") 33} 34 35fun main() { 36 println(createTable()) 37}
というコードが、ソースコードの全文となっています。
その中の
private operator fun String.unaryPlus() { TODO("Not yet implemented") }
というコードにおける
TODO("Not yet implemented")
という部分に何を書けばよいのかわからず、悩んでいます。
これが実装できれば、td 内に Hello が表示されるはずだと考えています。
###試したこと
children や append 、 (this + " ")のようなものを使うと予想しています。ただ、自信はありません。
kotlin in action という本のp294 及び
https://github.com/Kotlin/kotlin-by-example/blob/master/examples/09_Kotlin_JS/06_HtmlBuilder.md
上記のサイトを参考にしています。
###補足
Kotlin version: 1.3.72
Android Studio を使用しています。
###自己解決時に参考にしたコード
Kotlin
1interface Element { 2 fun render(builder: StringBuilder, indent: String) 3} 4 5class TextElement(private val text: String) : Element { 6 override fun render(builder: StringBuilder, indent: String) { 7 builder.append("$indent$text\n") 8 } 9} 10 11@DslMarker 12annotation class HtmlTagMarker 13 14@HtmlTagMarker 15abstract class Tag(val name: String) : Element { 16 val children = arrayListOf<Element>() 17 val attributes = hashMapOf<String, String>() 18 19 protected fun <T : Element> initTag(tag: T, init: T.() -> Unit): T { 20 tag.init() 21 children.add(tag) 22 return tag 23 } 24 override fun render(builder: StringBuilder, indent: String) { 25 builder.append("$indent<$name${renderAttributes()}>\n") 26 for (c in children) { 27 c.render(builder, "$indent ") 28 } 29 builder.append("$indent</$name>\n") 30 } 31 32 private fun renderAttributes(): String { 33 val builder = StringBuilder() 34 for ((attr, value) in attributes) { 35 builder.append(" $attr=\"$value\"") 36 } 37 return builder.toString() 38 } 39 override fun toString(): String { 40 val builder = StringBuilder() 41 render(builder, "") 42 return builder.toString() 43 } 44} 45abstract class TagWithText(name: String) : Tag(name) { 46 operator fun String.unaryPlus() { 47 children.add(TextElement(this)) 48 } 49} 50 51class HTML : TagWithText("html") { 52 fun head(init: Head.() -> Unit) = initTag(Head(), init) 53 54 fun body(init: Body.() -> Unit) = initTag(Body(), init) 55} 56 57class Head : TagWithText("head") { 58 fun title(init: Title.() -> Unit) = initTag(Title(), init) 59} 60 61class Title : TagWithText("title") 62 63abstract class BodyTag(name: String) : TagWithText(name) { 64 fun b(init: B.() -> Unit) = initTag(B(), init) 65 fun p(init: P.() -> Unit) = initTag(P(), init) 66 fun h1(init: H1.() -> Unit) = initTag(H1(), init) 67 fun a(href: String, init: A.() -> Unit) { 68 val a = initTag(A(), init) 69 a.href = href 70 } 71} 72class Body : BodyTag("body") 73class B : BodyTag("b") 74class P : BodyTag("p") 75class H1 : BodyTag("h1") 76 77class A : BodyTag("a") { 78 var href: String 79 get() = attributes["href"]!! 80 set(value) { 81 attributes["href"] = value 82 } 83} 84 85fun html(init: HTML.() -> Unit): HTML { 86 val html = HTML() 87 html.init() 88 return html 89}
このコードの
abstract class TagWithText(name: String) : Tag(name) { operator fun String.unaryPlus() { children.add(TextElement(this)) } }
という部分を参考にいたしました。
回答1件
あなたの回答
tips
プレビュー