Kotlin之DSL,GC+堆排+Tomcat+算法题

    • DSL构建布局
  • 前言

  • 一、What’s the DSL?

  • 二、初探

    • 1.DSL常见的应用
  • 三.koltin中的DSL

    • 1.扩展函数

    • 2.带接收者的 Lambda 表达式

    • 3.用DSL构建布局

  • 总结

    • 一.对于DSL构建的布局

    • 二. Compose


[](

)前言

=================================================================

入职新公司后发现kotlin的语法知识跟不上,因为公司开发团队的习惯问题,原先的公司还是java+kt混编开发的模式,许多同事基本不用kt,一些不常规的语法应用很少接触使用,还存在使用错误的情况,所以现在要补一些ktolin语法使用的知识,而DSL就是第一个点

[](

)一、What’s the DSL?

================================================================================

先上一小段可爱的代码:


ConstraintLayout {

            layout_width = wrap_content

            layout_height = wrap_content

            background_res = R.drawable.ic1



            ImageView {

                layout_width = 22

                layout_height = 22

                top_toTopOf = parent_id

                end_toEndOf = parent_id

                margin_top = 9

                margin_end = 5

                padding = 5

                scaleType = scale_fit_xy

                src = R.drawable.ic2

            }



            TextView {

                layout_id = "tv1"

                layout_width = wrap_content

                layout_height = wrap_content

                textColor = "#ff3f4658"

                textSize = 16f

                textRes = R.string.tv1

                center_horizontal = true

                top_toBottomOf = "iv"

                margin_top = 3

            }



            TextView {

                layout_id = "tv2"

                layout_width = wrap_content

                layout_height = wrap_content

                textColor = "#ffffff"

                textSize = 12f

                center_horizontal = true

                top_toBottomOf = "tv1"

                margin_top = 8

                text = "deo"

            }



        } 

土包子的我第一次看到这样的定义布局方式并没有感觉有啥新奇,不就是动态设置控件嘛,并没有什么高级的地方,反而觉得不如XML直观且无法预览,但一仔细看就不对了,按照常规的写法应该是从父布局开始逐个初始化对象,然后通过layouparmars设置布局属性添加到相应容器中,这种写法是什么情况,貌似直接嵌套还直接定义了控件属性,和xml的语法很像但貌似更简便(XML也可以看做是DSL)。此时只有一个字可以形容

在这里插入图片描述

通过偷偷摸摸的百度后知道这就是传说中的DSL构建的布局方式,这个东西是有了解过的,但没深入的看过(看完就忘),kt的部分语法感觉过于难以阅读所以一直抗拒(其实是菜看不懂),靠着apply、let、with苟延残喘的使用着,还感觉自己kt用的很nice。

这么陌生且高大上的词汇看的第一眼就感觉很难,自然反应的Google一下:

图一

给出的解释就是*领域专用语言***。 词汇太专业,依然不知道是啥。。。查的时候还看到另一个词:[GPL](

) ,有必要了解一下,General Purpose Language翻译过来就是通用语言,如Java、OC、C等等,这个好理解脑子一下就知道是啥了。这些语言使用很广泛,像java能 写android也能写后端,业务代码都是用这些语言写的。

对比一下GPL,DSL的针对性更强,只适用于特定的功能方向,就像文言文和白话文,一个用于作文记事,一个用于交际用语,举个可能不恰当的栗子,墓志铭就有特定的格式,第一他只能写给死人,第二有固定的格式,其他的像啥三言、五言、七言的,不是很准确但就是那个意思吧。

[](

)二、初探

===================================================================

[](

)1.DSL常见的应用


简单的了解过后感觉DSL更像是一种自己构建出来快捷的语法格式或者说结构,像最上面的布局代码其实最后做的工作应该和普通的写法(控件都最后都要初始化)是一样的,但对于项目来说大量频繁的重写就会省力很多且代码格式更好,当然好处不止于此。很多东西都见过也用过只是不知道原来这么D伊奥。

第一个众所周知的HTML就是典型的DSL,首先她不算是编程语言,它定义了特殊的网页结构标示不同的含义,还一个特点他不能像java那样写出复杂的逻辑,它们都是命令式的,瞬间清醒,此时DSL和GPL的区别通透了。

其他的一些我们接触过的包括Gradle、SQL,按照上面的特点,SQL语句能写逻辑吗?Gradle语法能写复杂逻辑吗?

他们的语句还有些共同点,仔细的回忆一下SQL、Gradle语句,是不是容易忘记,容易不认识,容易写错,可能一年没写过一条SQL的人大把抓,但他们都比较有特定的结构且只能用于实现特定功能,因为语法和常规的语言编写格式不同所以容易忘记。SQL编写语句管理数据,Gradle配置项目用于构建,HTML用于显示网页文本内容,而不像Java或者其他编程语言一样,没有特定的限制,想在哪用在哪用。

[](

)三.koltin中的DSL

============================================================================

要实现开头的布局方式需要怎么做呢?因为SDK也没定义这种规范,kt也没有直接提供,所以只能内部创造,手动满足。

在kotlin中实现DSL构建要靠两样东西:

.扩展函数;

.带接收者的 Lambda 表达式;

先说扩展函数,这个还是比较简单的。

[](

)1.扩展函数



fun String.customOperation(append:String) :String{

    return this+append

} 

上面写了个String的扩展函数,自定义了一个操作,对接受者拼接了append字符串,在其他地方可以把customOperation当做系统的api直接调用。扩展函数的作用也一目鸟然,可以封装频率使用高的操作代码,可以像使用原生API一样使用扩展方法。

再看一下字节码:


 // access flags 0x19

  public final static customOperation(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;

  @Lorg/jetbrains/annotations/NotNull;() // invisible

    // annotable parameter count: 2 (visible)

    // annotable parameter count: 2 (invisible)

    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 0

    @Lorg/jetbrains/annotations/NotNull;() // invisible, parameter 1

   L0

    ALOAD 0

    LDC "$this$customOperation"

    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkNotNullParameter (Ljava/lang/Object;Ljava/lang/String;)V

    ALOAD 1

    LDC "append"

    INVOKESTATIC kotlin/jvm/internal/Intrinsics.checkNotNullParameter (Ljava/lang/Object;Ljava/lang/String;)V

   L1

    LINENUMBER 11 L1

    NEW java/lang/StringBuilder

    DUP

    INVOKESPECIAL java/lang/StringBuilder.<init> ()V

    ALOAD 0

    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;

    ALOAD 1

    INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder;

    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;

    ARETURN

   L2

    LOCALVARIABLE $this$customOperation Ljava/lang/String; L0 L2 0

    LOCALVARIABLE append Ljava/lang/String; L0 L2 1

    MAXSTACK = 2

    MAXLOCALS = 2



  @Lkotlin/Metadata;(mv={1, 4, 0}, bv={1, 0, 3}, k=2, d1={"\u0000\n\n\u0000\n\u0002\u0010\u000e\n\u0002\u0008\u0002\u001a\u0012\u0010\u0000\u001a\u00020\u0001*\u00020\u00012\u0006\u0010\u0002\u001a\u00020\u0001\u00a8\u0006\u0003"}, d2={"customOperation", "", "append", "My_Application.app"})

  // compiled from: Extends.kt

} 

static 圈一下,一目了然,扩展方法被编译成静态方法,(Ljava/lang/String;Ljava/lang/String;) 圈一下,咦?怎么两个String呢?

[](

)2.带接收者的 Lambda 表达式


带接受者的Lambda是啥样子,首先函数式编程Lambda是kt的一大特色(简洁避免语法噪音),但高阶函数看起来就很累,阅读性感觉不太友好,过于简化(主要还是菜),rxjava、协程一起用的时候就更懵逼了,lowB的代码不香吗?

要知道啥是高阶函数,简单无脑的理解就是函数嵌套函数,在kt中lambda是可以当做参数进行传递的


fun createString(build:(StringBuilder)->Unit):String {

    val stringBuilder=StringBuilder()

    build(stringBuilder)

    return stringBuilder.toString()

} 

如果想要通过StringBuild去创建一个自定义的拼接字符串可以用上面的方法,比如:

这就是lambda作为参数传递的一个简单栗子,但是在调用createString 的时候,在表达式中需要显示的调用it,这个it就是StringBuilder,而这个表达式的调用者是期望或者我们已经指定了就是一个StringBuilder,所以可以避免这种显示调用的现象,在声明表达式的时候为它指定调用者,所以修改createString传入的表达式:


fun createString(build:StringBuilder.()->Unit):String {

    val stringBuilder=StringBuilder()

    build(stringBuilder)

    return stringBuilder.toString()

} 

这个时候可以看到调用函数的地方报错了

可以看到编译的提示,表达式的参数提示由it变成了this,这个时候我们直接可以使用StringBuilder的方法而不需要显示的使用it

在上面的方法中 build:StringBuilder.()->Unit就是一个带接受者的Lambda 表达式,它的声明语法格式是:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值