1、
fun main(args: Array<String>) {
//一个标准的html代码段
// <html>
// <head>
// </head>
//
// <body>
// <div>
// </div>
// </body>
// </html>
//我们发现这样定义html不方便,因为我们不是前端开发人员,能不能转化为用代码去实现呢?
var html=Tag("html")
println(html)
}
/**
* 于是我们定义这样一个数据类,构造方法出入标签名,并且重写它的toString方法,按我们想要的方式输出
*/
data class Tag(var name:String)
{
override fun toString(): String {
return "<$name></$name>"
}
}
输出:
我们把剩余的代码写完
fun main(args: Array<String>) {
//一个标准的html代码段
// <html>
// <head>
// </head>
//
// <body>
// <div>
// </div>
// </body>
// </html>
//我们发现这样定义html不方便,因为我们不是前端开发人员,能不能转化为用代码去实现呢?
var html=Tag("html")
var head=Tag("head")
html.addTag(head)
var body=Tag("body")
html.addTag(body)
var div=Tag("div")
body.addTag(div)
println(html)
}
/**
* 于是我们定义这样一个数据类,构造方法出入标签名,并且重写它的toString方法,按我们想要的方式输出
*/
data class Tag(var name:String)
{
//因为标签中可以包含其他标签,并且可能包含多个,所以需要定义一个集合存储
var list= mutableListOf<Tag>()
//定义方法,可以往集合中添加标签
fun addTag(tag:Tag)
{
list.add(tag)
}
//重写toString方法,因为需要输出它自己以及它的子标签
override fun toString(): String {
var stringBuilder=StringBuilder()
stringBuilder.append("<$name>")
list.forEach {
stringBuilder.append(it.toString())
}
stringBuilder.append("</$name>")
return stringBuilder.toString()
}
}
输出:
2、我们把每个标签都定义为一个类,简化定义流程
fun main(args: Array<String>) {
var html=Html()
var head=Head()
var body=Body()
var div=Div()
html.addTag(head)
head.addTag(body)
body.addTag(div)
println(html)
}
class Html:Tag("Html")
class Head:Tag("head")
class Body:Tag("body")
class Div:Tag("div")
/**
* 于是我们定义这样一个数据类,构造方法出入标签名,并且重写它的toString方法,按我们想要的方式输出
*/
open class Tag(var name:String)
{
//因为标签中可以包含其他标签,并且可能包含多个,所以需要定义一个集合存储
var list= mutableListOf<Tag>()
//定义方法,可以往集合中添加标签
fun addTag(tag:Tag)
{
list.add(tag)
}
//重写toString方法,因为需要输出它自己以及它的子标签
override fun toString(): String {
var stringBuilder=StringBuilder()
stringBuilder.append("<$name>")
list.forEach {
stringBuilder.append(it.toString())
}
stringBuilder.append("</$name>")
return stringBuilder.toString()
}
}
输出:
但是还不方便,我们想要的定义效果是这样:
head{
}
body
{
div{
}
}
}
简单直观
3、定义DSL
fun main(args: Array<String>) {
html {
head {
}
body {
div {
}
}
}
}
//根据上节的分析我们就直接写代码了
fun html(block:()->Unit):String
{
var html=Html()
return html.toString()
}
fun head(block:()->Unit)
{
var head=Head()
}
fun body(block:()->Unit)
{
var body=Body()
}
fun div(block: () -> Unit)
{
var div=Div()
}
代码没有报错,接下来完善head方法
fun Html.head(block:()->Unit)
{
var head=Head()
//这儿必须得调用Html对象的addTag方法才能把自己添加进去,所以必须得能够访问到Html对象
//于是把他定义成Html的扩展方法
}
但是发现这儿报错了
为什么head识别不了了,我们分析下代码,head方法已经是Html对象的扩展方法了,
fun html(block:Html.()->Unit):String
{
var html=Html()
return html.toString()
}
完善代码
fun html(block:Html.()->Unit):String
{
var html=Html()
block.invoke(html)
return html.toString()
}
fun Html.head(block:()->Unit)
{
var head=Head()
//这儿必须得调用Html对象的addTag方法才能把自己添加进去,所以必须得能够访问到Html对象
//于是把他定义成Html的扩展方法
block.invoke()
this.addTag(head)
}
剩余两个标签类似
4、完整代码:
fun main(args: Array<String>) {
var h=html {
head {
}
body {
div {
}
}
}
println(h)
}
//根据上节的分析我们就直接写代码了
fun html(block:Html.()->Unit):String
{
var html=Html()
block.invoke(html)
return html.toString()
}
fun Html.head(block:()->Unit)
{
var head=Head()
//这儿必须得调用Html对象的addTag方法才能把自己添加进去,所以必须得能够访问到Html对象
//于是把他定义成Html内部的方法
this.addTag(head)
block.invoke()
}
fun Html.body(block:Body.()->Unit)
{
var body=Body()
this.addTag(body)
block.invoke(body)
}
fun Body.div(block: () -> Unit)
{
var div=Div()
this.addTag(div)
block.invoke()
}
class Html:Tag("Html")
class Head:Tag("head")
class Body:Tag("body")
class Div:Tag("div")
/**
* 于是我们定义这样一个数据类,构造方法出入标签名,并且重写它的toString方法,按我们想要的方式输出
*/
open class Tag(var name:String)
{
//因为标签中可以包含其他标签,并且可能包含多个,所以需要定义一个集合存储
var list= mutableListOf<Tag>()
//定义方法,可以往集合中添加标签
fun addTag(tag:Tag)
{
list.add(tag)
}
//重写toString方法,因为需要输出它自己以及它的子标签
override fun toString(): String {
var stringBuilder=StringBuilder()
stringBuilder.append("<$name>")
list.forEach {
stringBuilder.append(it.toString())
}
stringBuilder.append("</$name>")
return stringBuilder.toString()
}
}
输出: