嵌套类、内部类、对象表达式
嵌套类
一个类可以嵌套在另一个类里面:
class OuterClass {
class NestedClass {
fun method() {
println("hello")
}
}
}
fun main() {
var outerClass = OuterClass.NestedClass()
outerClass.method()
}
内部类
内部类与嵌套类类似,都是声明在另一个类里面,只不过多了一个关键字inner
。
class Outer {
var str = "hello"
inner class InnerClass {
fun method() {
println(str)
println(this@Outer.str)
}
}
}
fun main() {
var outer = Outer().InnerClass()
outer.method()
}
嵌套类与内部类的区别与联系:
- 嵌套类:对应java内部的静态内部类(有static关键字修饰)
- 内部类:对应java内部的非静态内部类(没有static关键字修饰),可以访问外部类的属性。
局部嵌套类:定义在方法内部的类。
fun getName(): String {
class LocalNestedClass {
var name = "morris"
}
var localNestedClass = LocalNestedClass()
return localNestedClass.name
}
对象表达式
kotlin中的匿名内部类使用对象表达式(object expression:)来创建。
匿名内部类是没有名字的,需要继承某个父类,或者实现了某个接口:
interface MyInterface {
fun print(i: Int)
}
fun main() {
var myInterface = object : MyInterface {
override fun print(i: Int) {
println("print $i")
}
}
myInterface.print(1024)
}
匿名内部类可以不支持显示的父类,默认为Any。
var obj = object {
fun method(name: String) {
println("print $name")
}
}
obj.method("morris")
匿名内部类可以实现一个父类或多个接口(java只能实现一个)。
interface MyInterface {
fun print(i: Int)
}
abstract class MyAbstract {
abstract val age: Int
abstract fun method(name: String)
}
fun main() {
var myclass = object : MyAbstract(), MyInterface {
override fun print(i: Int) {
println("print $i")
}
override val age: Int
get() = 10
override fun method(name: String) {
println("print name=$name age=$age")
}
}
myclass.print(1024)
myclass.method("morris")
}
匿名对象只能在局部变量范围内或者被private修饰的成员变量范围内才能真正识别出其具体类型,如果匿名对象作为一个public方法的返回值或者public的属性,那么外部能识别到的只有该匿名对象的父类型,如果没有声明任何父类型,那么就是默认的Any,在这种情况下,匿名对象中声明的任何成员都是无法访问的。
class MyClass {
// 不使用private,下面的test()中无法调用hello()方法
private var obj = object {
fun hello(){
println("hello")
}
}
fun test() {
obj.hello()
}
}
与java中的匿名内部类不同,kotlin中的内部类可以修改外部的变量,外部的变量也不需要设置为final。
fun main() {
var age = 10
var obj = object {
fun hello(){
println("print ${++age}")
}
}
obj.hello() // print 11
}
如果接口是一个函数式接口,使用lambda表达式更简洁:
val listener = ActionListener { println("clicked") }