Kotlin系列(十九):嵌套类、内部类与this的特殊用法
目录
- 更多分享:www.catbro.cn
一、前言:
-
我们之前学习了Kotlin类相关的知识,包括类的定义、类成员的定义、类的继承、成员的重写等,我们还学习了可见性修饰符。
-
本章我们将继续学习类方面的知识:嵌套类、内部类和特殊场景下this的使用。
二、嵌套类
-
类可以嵌套在其他类中:
class Outer { private val bar: Int = 1 class Nested { fun foo() = 2 } } val demo = Outer.Nested().foo() // == 2
三、内部类
-
内部类用 inner标记,通过inner标记的内部类能够访问外部类的成员。
-
内部类会带有一个对外部类的对象的引用:
class Outer { private val bar: Int = 1 inner class Inner { fun foo() = bar } } val demo = Outer().Inner().foo() // == 1
四、匿名内部类
-
在Java中我们经常会用到接口这个东西
-
我们来下Java中如何实现:
-
首先、线定义一个接口类:
/** * Created by 安杰 on 2017/10/27. */ public class UserLisenter { interface onClickListener { void onClick1(int i); void onClick2(int j); } public void addLisenter(onClickListener lisenter) { } }
-
然后我们是实现这么一个接口类:
import org.junit.Test; /** * Created by 安杰 on 2017/10/27. */ public class TestJava { @Test public void test() { UserLisenter userLisenter = new UserLisenter(); userLisenter.addLisenter(new UserLisenter.onClickListener() { @Override public void onClick1(int i) { } @Override public void onClick2(int j) { } }); } }
-
Ok,我们再看一下Kotlin的版本,再Kotlin中我们可以通过创建匿名内部类来实现,也就是没有名字的类;
@Test fun test2() { val u = UserLisenter(); u.addLisenter(object : UserLisenter.onClickListener { override fun onClick1(i: Int) { } override fun onClick2(j: Int) { } }) }
-
当然,如果我们的接口里面只有一个回调函数,我们还可以直接用lambda表达式。
-
代码修改如下:
/** * Created by 安杰 on 2017/10/27. */ public class UserLisenter { interface onClickListener { void onClick1(int i); } public void addLisenter(onClickListener lisenter) { } }
-
实现代码如下:
@Test fun test2() { val u = UserLisenter(); u.addLisenter { i -> //实现代码 } }
五、This 表达式
- 一旦用到内部类、嵌套类或者lambda表达式,我们需要使用外面的数据时,就需要特殊处理我们的this了。
- 为了表示当前的 接收者 我们使用 this 表达式:
- 在类的成员中,this 指的是该类的当前对象。
- 在扩展函数或者带接收者的函数字面值中, this表示在点左侧传递的 接收者 参数。
- 如果 this没有限定符,它指的是最内层的包含它的作用域。要引用其他作用域中的 this,请使用 标签限定符:
限定的 this
-
要访问来自外部作用域的this,我们使用
this@label
,其中@label
是一个代指 this 来源的标签:@Test fun test2() { var name = "test2" class A { // 隐式标签 @A var name = "A"; inner class B { // 隐式标签 @B var name = "B"; fun say() { val a = this@A.name // 类A 的 this println("this@A $a") val b = this@B.name // 类B 的 this println("this@B $b") val c = this.name println("this $c") val funLit2 = { s: String -> val d1 = this.name; println("funLit2 this $d1") } funLit2("funLit2 name"); } } } val a = A().B(); a.say(); }
-
运行结果为:
this@A A this@B B this B funLit2 this B
-
结果分析:
-
可以看到,通过@类名可直接获取外部类的this引用。
-
在lambda表达式中this指向外面第一层的类B。