kotlin lambda之 “带接受者的lambda”

<div id="content_views" class="markdown_views prism-atom-one-dark">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <h1><a name="t0"></a><a id="lambda_0"></a><a href="https://so.csdn.net/so/search?q=lambda&amp;spm=1001.2101.3001.7020" target="_blank" class="hl hl-1" data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.7020&quot;,&quot;dest&quot;:&quot;https://so.csdn.net/so/search?q=lambda&amp;spm=1001.2101.3001.7020&quot;,&quot;extra&quot;:&quot;{\&quot;searchword\&quot;:\&quot;lambda\&quot;}&quot;}" data-tit="lambda" data-pretit="lambda">lambda</a>基础</h1> 
<p>lambda这一块是<a href="https://so.csdn.net/so/search?q=kotlin&amp;spm=1001.2101.3001.7020" target="_blank" class="hl hl-1" data-report-click="{&quot;spm&quot;:&quot;1001.2101.3001.7020&quot;,&quot;dest&quot;:&quot;https://so.csdn.net/so/search?q=kotlin&amp;spm=1001.2101.3001.7020&quot;,&quot;extra&quot;:&quot;{\&quot;searchword\&quot;:\&quot;kotlin\&quot;}&quot;}" data-tit="kotlin" data-pretit="kotlin">kotlin</a>一大难点,作为初学者,本篇文章记录一下学习历程。主要讨论了labmda的基本语法,以及带有接受者的lambda这种特殊语法的含义。</p> 
<h2><a name="t1"></a><a id="_3"></a>基本语法</h2> 
<p>Lambda 表达式的完整语法形式如下:</p> 
<pre data-index="0" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">val sum: (Int, Int) -&gt; Int = { x: Int, y: Int -&gt; x + y }
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li></ul></pre> 
<p>lambda 表达式总是括在花括号中, 完整语法形式的参数声明放在花括号内,并有可选的类型标注, 函数体跟在一个 -&gt; 符号之后。如果推断出的该 lambda 的返回类型不是 Unit,那么该 lambda 主体中的最后一个(或可能是单个) 表达式会视为返回值。</p> 
<h2><a name="t2"></a><a id="lambda_13"></a>lambda的语法糖</h2> 
<pre data-index="1" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">//编译器类型推断,简化类型声明
val sum = { x: Int, y: Int -&gt; x + y }

//当lambda表达式作为函数的末尾参数时
//可以放在圆括号之外
val product = items.fold(1) { acc, e -&gt; acc * e }

//如果lambda是函数的唯一参数
//可以省略圆括号
run { println("...") }

//当lambda只有一个参数,且参数类型可以被推断出
//会自动生成一个it代替参数
val ss = "hello".filter { it &gt; 's' } 
val ss = "hello".filter { param: Char -&gt; param &gt; 's'}

//lambda默认返回最后一行表达式的value
//也可以用限定符显式返回
val ss = "hello".filter {
    val filterMethod = it &gt; 's'
    filterMethod
}
val ss = "hello".filter {
    val filterMethod = it &gt; 's'
    return@filter filterMethod
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li></ul></pre> 
<p>注意,labmda是表达式的语法,很多情况下与函数结合使用,由于函数也存在一些语法糖,所以容易把二者混为一谈</p> 
<pre data-index="2" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">//当函数只有一个表达式时,可以省略大括号,以‘=’连接
//这个特性和lambda没有关系
fun test(block: ()-&gt;Unit) = block() 
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li></ul></pre> 
<h2><a name="t3"></a><a id="lambda_52"></a>带有接受者的lambda</h2> 
<p>在考虑这个问题前,从简单的lambda开始分析<br> 说明:示例代码中的函数和类,如没有改动,就复用上一个代码块的内容</p> 
<h3><a name="t4"></a><a id="block__A__Unit_57"></a>block : (A) -&gt; Unit</h3> 
<p>简单的lambda中,参数一般是8种基本类型。稍微复杂的lambda,需要传递自定义类型的对象。我们可以写成</p> 
<pre data-index="3" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    fun doSomething() {
        print("A do something\n")
    }
}

fun main() {   
    //这个lambda变量,接收一个A类型的参数,并执行一些操作
    val block: (A) -&gt; Unit = { objectA: A -&gt;
        objectA.doSomething()
    }
    //根据上述语法糖,简写为
    val block: (A) -&gt; Unit = {
        it.doSomething()    
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li></ul></pre> 
<ul><li>如果将带有自定义对象参数的lambda,作为另一个函数的参数,可以写成</li></ul> 
<pre data-index="4" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun demoOne(block: (A) -&gt; Unit) {
    print("demoOne Done\n")
}

fun main() {
    val block: (A) -&gt; Unit = {
        it.doSomething()    
    }
    demoOne(block)
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702192821638.png" alt="在这里插入图片描述"><br> 这很合理,因为demoOne()里没有任何调用block的代码。</p> 
<ul><li>那么如何使用这种lambda呢,可以写成</li></ul> 
<pre data-index="5" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun demoOne(block: (A) -&gt; Unit) {
    val a = A()
    block(a)
    print("demoOne Done\n")
}

fun main() {
    //这里用语法糖简化
    demoOne {
        it.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702192922355.png" alt="在这里插入图片描述"><br> 很简单,这个lambda需要一个A类型的参数,所以new一个送进去即可</p> 
<ul><li>事实上,上述使用方法,还有几种类似的写法</li></ul> 
<pre data-index="6" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun demoOne(block: (A) -&gt; Unit) {
    block.invoke(A())
    print("demoOne Done\n")
}

fun demoOne(block: (A) -&gt; Unit) {
    A().apply(block)
    print("demoOne Done\n")
}

fun demoOne(block: (A) -&gt; Unit) {
    A().apply {
        block(this)    
    }
    print("demoOne Done\n")
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702192950337.png" alt="在这里插入图片描述"><br> 运行结果都相同。至于原理,请见下文</p> 
<ul><li>如果我不仅想调用A的方法,还想调A的属性,可以写成</li></ul> 
<pre data-index="7" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    val aa = "NAME A\n"
    
    fun doSomething() {
        print("A do something\n")
    }
}

fun demoOne(block: (A) -&gt; Unit) {
    block(A())
    print("demoOne Done\n")
}

fun main() {
    demoOne {
        print(it.aa)
        it.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{&quot;spm&quot;:&quot;1001.2101.3001.7365&quot;}"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193003572.png" alt="在这里插入图片描述"><br> 这也很合理,因为传入demoOne的这个lambda里,it是一个匿名的A的对象,访问自己的属性当然能访问到。注意这里的aa是公有的,如果写成private,就需要暴露一个公有方法来间接访问。</p> 
<ul><li>上面都是针对A的属性和方法,那能不能在传入的lambda中操作其他类的属性和方法。可以写成</li></ul> 
<pre data-index="8" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    val aa = "NAME A\n"
    
    fun doSomething() {
        print("A do something\n")
    }
}

class B {
    val bb = "NAME B\n"
    
    fun doSomething() {
        print("B do something\n")
    }
}

fun demoOne(block: (A) -&gt; Unit) {
    block(A())
    print("demoOne Done\n")
}

fun main() {
    var b = B()
    demoOne {
        print(b.bb)
        b.doSomething()
        print(it.aa)
        it.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193024694.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xqamxpdWp1bmppZTEyMw==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br> 可以发现在传入lambda时,可以操作其他类。原理见下文。</p> 
<ul><li>总结一下,对于block: (A) -&gt; Unit这种lambda的基本使用。完整demo代码</li></ul> 
<pre data-index="9" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    val aa = "NAME A\n"
    
    fun doSomething() {
        print("A do something\n")
    }
}

class B {
    val bb = "NAME B\n"
    
    fun doSomething() {
        print("B do something\n")
    }
}

fun demoOne(block: (A) -&gt; Unit) {
    block(A())
    print("demoOne Done\n")
}

fun main() {
    var b = B()
    demoOne {
        print(b.bb)
        b.doSomething()
        print(it.aa)
        it.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li></ul></pre> 
<h3><a name="t5"></a><a id="block_A__Unit_231"></a>block: A.() -&gt; Unit</h3> 
<p>下面可以开始学习“带有接收者的lambda”这个概念<br> 官方文档对应部分 http://www.kotlincn.net/docs/reference/lambdas.html</p> 
<ul><li>从最基本的调用开始</li></ul> 
<pre data-index="10" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    val aa = "NAME A\n"
    
    fun doSomething() {
        print("A do something\n")
    }
}

fun demoTwo(block: A.() -&gt; Unit) {
    print("demoOne Done\n")
}

fun main() {   
    //这里仿照上一个例子,写一个lambda
    **val block: A.() -&gt; Unit = { Afunc: A.() -&gt;
        Afunc()
    }
    
    val block: A.() -&gt; Unit = { Afunc: A -&gt;
        Afunc()
    }**
    //正确的写法
    val block: A.() -&gt; Unit = {
        //to do
    }
    demoTwo(block)
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li></ul></pre> 
<p>上述加粗代码是编不过的,编译器会提示Expected no parameters,也就是说这种lambda不接收参数?<br> 正确代码运行结果如下。很容易理解,传递了一个空的lambda自然什么都不会做<br> <img src="https://img-blog.csdnimg.cn/20210702193044684.png" alt="在这里插入图片描述"></p> 
<ul><li>仿照block: (A) -&gt; Unit的写法,如何调用到A的方法呢</li></ul> 
<pre data-index="11" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    val aa = "NAME A\n"
    
    fun doSomething() {
        print("A do something\n")
    }
}

fun demoTwo(block: A.() -&gt; Unit) {
    block(A())
    block.invoke(A())
    A().block()
    A().apply(block)
    A().apply {
        block(this)
    }
    A().apply {
        this.block()
    }
    print("demoOne Done\n")
}

fun main() {   
    demoTwo {
        doSomething()
        //还可以写成。注意这一处变化
        //this.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{&quot;spm&quot;:&quot;1001.2101.3001.7365&quot;}"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193116121.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xqamxpdWp1bmppZTEyMw==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br> 上述6种写法都能run,而block: (A) -&gt; Unit有下面4种写法。</p> 
<pre data-index="12" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun demoOne(block: (A) -&gt; Unit) {
    block(A())
    block.invoke(A())
    A().apply(block)
    A().apply {
        block(this)
    }
    print("demoOne Done\n")
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li></ul></pre> 
<p>首先考虑二者共有的四种调用方法。对于block: (A) -&gt; Unit来说,其接收一个A类型的对象,有了A的实例,这四种调用都是显而易见成立的。但对于block: A.() -&gt; Unit,为什么也能run呢,原因放到原理部分分析。<br> 然后考虑新增的A().block()和A().apply{this.block()}。直观上看起来,似乎block是A的一个成员方法,但显然,block是一个独立的lambda。那为啥A()能直接调block呢,是不是有点像扩展方法。具体和扩展有何异同,在原理部分分析。</p> 
<ul><li>如何调用A的属性呢,很容易写出</li></ul> 
<pre data-index="13" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun main() {   
    demoTwo {
        //同样注意,这里我们是直接访问的,说明this指针指向A
        print(aa)
        doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193138781.png" alt="在这里插入图片描述"></p> 
<ul><li>再考虑操作类的属性和方法</li></ul> 
<pre data-index="14" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class B {
    val bb = "NAME B\n"
    
    fun doSomething() {
        print("B do something\n")
    }
}

fun main() {   
    var b = B()
    demoTwo {
        print(aa)
        doSomething()
        print(b.bb)
        b.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{&quot;spm&quot;:&quot;1001.2101.3001.7365&quot;}"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193152385.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xqamxpdWp1bmppZTEyMw==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"></p> 
<ul><li>看起来和block : (A)-&gt; Unit的操作没区别。考虑下面这个特殊情况</li></ul> 
<pre data-index="15" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun main() {   
    fun doSomething() {
        print("main do something\n")
    }
    
    var b = B()
    demoTwo {
        print(aa)
        doSomething()
        this.doSomething()
        print(b.bb)
        b.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193224974.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2xqamxpdWp1bmppZTEyMw==,size_16,color_FFFFFF,t_70" alt="在这里插入图片描述"><br> 根据上述的分析,demoTwo传入的lambda中,this指针默认指向A。但是这里所说的默认,其优先级仍然是低于局部变量的,如有同名的方法和属性,优先走局部变量。如果需要明确制定A,只需要显式使用this指针即可。</p> 
<ul><li>总结一下,block: A.() -&gt; Unit 的基本使用demo代码</li></ul> 
<pre data-index="16" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    val aa = "NAME A\n"
    
    fun doSomething() {
        print("A do something\n")
    }
}

class B {
    val bb = "NAME B\n"
    
    fun doSomething() {
        print("B do something\n")
    }
}

fun demoTwo(block: A.() -&gt; Unit) {
    block(A())
    print("demoOne Done\n")
}

fun main() {   
    fun doSomething() {
        print("main do something\n")
    }
    
    var b = B()
    demoTwo {
        print(aa)
        doSomething()
        this.doSomething()
        print(b.bb)
        b.doSomething()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li></ul></pre> 
<h2><a name="t6"></a><a id="_414"></a>原理探索</h2> 
<p>虽然基本用法可以通过试错搞出来,但不懂原理遇到bug就gg了。所以来尝试瞟一眼原理<br> 先写一个简单的调用对比</p> 
<pre data-index="17" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun main() {
    demoOne { 
        it.doSomething()
    }
    demoTwo { 
        doSomething()
        this.doSomething()
    }
}

fun demoOne(block: (A) -&gt; Unit) {
    block.invoke(A())
    print("1\n")
}

fun demoTwo(block: A.() -&gt; Unit) {
    block.invoke(A())
    print("2\n")
}

class A()
{
    fun doSomething() {
        print("A do something \n")
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt" data-report-view="{&quot;spm&quot;:&quot;1001.2101.3001.7365&quot;}"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li></ul></pre> 
<p>直接反编译,整理一下代码</p> 
<pre data-index="18" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">public final class DemoKt {
   public static final void main() {
      demoOne((Function1)null.INSTANCE);
      demoTwo((Function1)null.INSTANCE);
   }

   // $FF: synthetic method
   public static void main(String[] var0) {
      main();
   }

   public static final void demoOne(@NotNull Function1 block) {
      Intrinsics.checkParameterIsNotNull(block, "block");
      block.invoke(new A());
      String var1 = "1\n";
      boolean var2 = false;
      System.out.print(var1);
   }

   public static final void demoTwo(@NotNull Function1 block) {
      Intrinsics.checkParameterIsNotNull(block, "block");
      block.invoke(new A());
      String var1 = "2\n";
      boolean var2 = false;
      System.out.print(var1);
   }
}
// A.java
public final class A {
   public final void doSomething() {
      String var1 = "A do something \n";
      boolean var2 = false;
      System.out.print(var1);
   }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li></ul></pre> 
<p>发现了神奇的事情,demoOne和demoTwo传入的参数,都是Function1类型的。众所周知,kt中的函数是一等公民,其类型由Function0、Function1、Function2等等一直到Function22。其数字代表函数的参数个数。但是我们在前面学习demoTwo的调用时,下面的写法是报错的,提示Expected no parameters。</p> 
<pre data-index="19" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">val block: A.() -&gt; Unit = { Afunc: A.() -&gt;
        Afunc()
    }
    
val block: A.() -&gt; Unit = { Afunc: A -&gt;
        Afunc()
    }
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li></ul></pre> 
<p>如果想继续深究为什么,需要考察A.()这个语法机制的设计原理。我们不必理解这么深,只要注意到上述反编译代码中,demoOne和demoTwo的方法体是完全一样的。特别是block.invoke(new A()) 这一条真正的调用指令。结合官方文档中这句话<br> 在这样的函数字面值内部,传给调用的接收者对象成为隐式的this,以便访问接收者对象的成员而无需任何额外的限定符,亦可使用 this 表达式 访问接收者对象<br> 我们可以得出初步结论,所谓带接受者的lambda就是把接受者对象作为隐式的this指针传入,替代了原本作用域的this。<br> 举个例子</p> 
<pre data-index="20" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class test {
    var name = "test\n"
    init {
        var name = "init\n"
        demoOne {
           print(name) //局部变量最高优先级,所以是init
           print(it.name) //it匿名A对象,所以是aa
           print(this.name) //this指向当前作用域的对象,所以是test
        }
        demoTwo {
           print(name)//局部变量最高优先级,所以是init
           print(this.name) //A.()语法隐式改写了this指针,所以是aa
        }
    }
}

class A()
{
    var name = "aa\n"
    fun doSomething() {
        print("A do something \n")
    }
}

fun demoOne(block: (A) -&gt; Unit) {
    block.invoke(A())
}

fun demoTwo(block: A.() -&gt; Unit) {
    block.invoke(A())
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li></ul></pre> 
<p><img src="https://img-blog.csdnimg.cn/20210702193253251.png" alt="在这里插入图片描述"></p> 
<ul><li>还剩下最后一个问题,A.() -&gt; Unit这种lambda语法和扩展有什么异同?</li></ul> 
<pre data-index="21" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    var aa = "aa"
}

fun A.printA() {
    print(aa)
}

class B {
    var a = A()
    init {
        a.printA()
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li></ul></pre> 
<p>反编译</p> 
<pre data-index="22" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">public final class B {
   @NotNull
   private A a = new A();

   @NotNull
   public final A getA() {
      return this.a;
   }

   public final void setA(@NotNull A var1) {
      Intrinsics.checkParameterIsNotNull(var1, "&lt;set-?&gt;");
      this.a = var1;
   }

   public B() {
      DemoKt.printA(this.a);
   }
}

// DemoKt.java
public final class DemoKt {
   public static final void printA(@NotNull A $this$printA) {
      Intrinsics.checkParameterIsNotNull($this$printA, "$this$printA");
      String var1 = $this$printA.getAa();
      boolean var2 = false;
      System.out.print(var1);
   }
}
// A.java
public final class A {
   @NotNull
   private String aa = "aa";

   @NotNull
   public final String getAa() {
      return this.aa;
   }

   public final void setAa(@NotNull String var1) {
      Intrinsics.checkParameterIsNotNull(var1, "&lt;set-?&gt;");
      this.aa = var1;
   }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li><li style="color: rgb(153, 153, 153);">25</li><li style="color: rgb(153, 153, 153);">26</li><li style="color: rgb(153, 153, 153);">27</li><li style="color: rgb(153, 153, 153);">28</li><li style="color: rgb(153, 153, 153);">29</li><li style="color: rgb(153, 153, 153);">30</li><li style="color: rgb(153, 153, 153);">31</li><li style="color: rgb(153, 153, 153);">32</li><li style="color: rgb(153, 153, 153);">33</li><li style="color: rgb(153, 153, 153);">34</li><li style="color: rgb(153, 153, 153);">35</li><li style="color: rgb(153, 153, 153);">36</li><li style="color: rgb(153, 153, 153);">37</li><li style="color: rgb(153, 153, 153);">38</li><li style="color: rgb(153, 153, 153);">39</li><li style="color: rgb(153, 153, 153);">40</li><li style="color: rgb(153, 153, 153);">41</li><li style="color: rgb(153, 153, 153);">42</li><li style="color: rgb(153, 153, 153);">43</li></ul></pre> 
<p>在B的init里调用printA方法时,实际调用了DemoKT的方法,因为扩展并不是真正改写了A类。而DemoKt::printA()接受的是A类型的对象,真正的方法体也是写在DemoKt::printA()里。<br> 对比lambda,主要的区别是传递给DemoKt的参数不一样,一个是A的对象,一个是Function对象<br> 应用</p> 
<ul><li>带有接受者的lambda被推荐用于DSL的实现,但不会用DSL,所以这块暂且跳过</li><li>根据官方文档的示例,发现这种lambda语法或许可以用于设计工厂方法,代码如下。这种写法没啥性能优势,感觉唯一的好处是增强了A的抽象能力和复用能力。A里提供了一堆基础属性和方法,消费者可以随意传入一个method,对这些属性和方法进行改写和调用。</li></ul> 
<pre data-index="23" class="set-code-hide prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">class A {
    companion object {
        fun createA(method: A.() -&gt; Unit): A {
                //相当于执行者
                var a = A()
                a.method()
                return a
            }
    }
    //这里只是定义一个变量,可以搞得更复杂一些
    var aa = "none"  
}

fun main() {
    //通过lambda定义不同的method
    //来生产不同的产品
    val firstA = A.createA {
        //相当于设计稿
        this.aa = "first"
    }
    val secondA = A.createA {
        this.aa = "second"
    }
}
<div class="hljs-button {2}" data-title="复制"></div></code><div class="hide-preCode-box"><span class="hide-preCode-bt"><img class="look-more-preCode contentImg-no-view" src="https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png" alt="" title=""></span></div><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li><li style="color: rgb(153, 153, 153);">3</li><li style="color: rgb(153, 153, 153);">4</li><li style="color: rgb(153, 153, 153);">5</li><li style="color: rgb(153, 153, 153);">6</li><li style="color: rgb(153, 153, 153);">7</li><li style="color: rgb(153, 153, 153);">8</li><li style="color: rgb(153, 153, 153);">9</li><li style="color: rgb(153, 153, 153);">10</li><li style="color: rgb(153, 153, 153);">11</li><li style="color: rgb(153, 153, 153);">12</li><li style="color: rgb(153, 153, 153);">13</li><li style="color: rgb(153, 153, 153);">14</li><li style="color: rgb(153, 153, 153);">15</li><li style="color: rgb(153, 153, 153);">16</li><li style="color: rgb(153, 153, 153);">17</li><li style="color: rgb(153, 153, 153);">18</li><li style="color: rgb(153, 153, 153);">19</li><li style="color: rgb(153, 153, 153);">20</li><li style="color: rgb(153, 153, 153);">21</li><li style="color: rgb(153, 153, 153);">22</li><li style="color: rgb(153, 153, 153);">23</li><li style="color: rgb(153, 153, 153);">24</li></ul></pre> 
<h2><a name="t7"></a><a id="_640"></a>结语</h2> 
<p>还有很多点没有学习到,比如A.(B) -&gt; C 可以与 (A,B) -&gt; C相互转换,以及如下代码的区别。等等…</p> 
<pre data-index="24" class="prettyprint"><code class="has-numbering" οnclick="mdcp.copyCode(event)" style="position: unset;">fun a(block:()-&gt;Unit) {block.invoke()}
fun a(block:()-&gt;Unit) = {block.invoke()} //这种写法下block是无法执行的
<div class="hljs-button {2}" data-title="复制"></div></code><ul class="pre-numbering" style=""><li style="color: rgb(153, 153, 153);">1</li><li style="color: rgb(153, 153, 153);">2</li></ul></pre>
                </div>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值