第二十八节 DSL练习

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>"
    }
}

输出:


image.png

我们把剩余的代码写完

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()
    }
}

输出:


image.png

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()
    }
}

输出:


image.png

但是还不方便,我们想要的定义效果是这样:

        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的扩展方法

}

但是发现这儿报错了


image.png

为什么head识别不了了,我们分析下代码,head方法已经是Html对象的扩展方法了,


image.png
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()
    }
}

输出:


image.png
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容