嵌套类
嵌套类(Nested Class)就是嵌套在另外一个类当中的类,换句话说,我定义一个类,然后在这个类的里面又去定义一个类。在Java里面有内部类的概念。Kotlin和Java这一点是比较类似,但是有一些区别。
class OutClass {
private val str: String = "hello world"
class NestedClass {
fun nestedMethod() = "welcome"
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main10)
OutClass.NestedClass().nestedMethod()
}
这是一个典型的嵌套类的事例。表面上看和Java的内部类挺像的,但是有一些明显的不同。
内部类
内部类也是在一个类的里面去定义一个类,但是内部类(Inner Class)需要在类的前面加关键字inner,明确表示这个是个内部类。
class OutClass2 {
private val str: String = "hello world"
inner class InnerClass {
fun innerMethod() = "welcome"
}
}
在内部类里面去访问外部类的成员变量的方式是[email protected]
class OutClass2 {
private val str: String = "hello world"
inner class InnerClass {
fun innerMethod() [email protected]
}
}
调用内部类的innerMethod()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main10)
OutClass2().InnerClass().innerMethod()
}
接下来分析下嵌套类和内部类存在怎么的关系,为什么调用方式是不一样的?
OutClass.NestedClass().nestedMethod()
OutClass2().InnerClass().innerMethod()
回忆一下Java的内部类,是否静态来划分有静态内部类和非静态内部类。但是Kotlin是没有static关键字的,也就是说没有静态属性和静态方法的。那Kotlin如何映射到Java的静态内部类和非静态内部类呢,是通过嵌套类和内部类这样俩种情况进行分别的映射。
关于嵌套类和内部类之间的区别与联系:
1.嵌套类:对应于Java的静态内部类(即有static关键字修饰的内部类),只要在一个类的内部定义了另外一个类,那么这个类就叫做嵌套类。相当于Java当中有static关键字修饰的内部类。
2.内部类:对应于Java中的非静态内部类(即没有static关键字修饰的内部类),使用inner关键字在一个类的内部定义另一个类就叫做内部类。相当于Java当中没有static关键字修饰的内部类。
这就是为什么嵌套类和内部类调用的方式是不一样的。静态类是可以直接用类名直接去引用,不用去创建对象。
局部嵌套类
定义在一个方法里面的一个嵌套类
class OutClass2 {
private val str: String = "hello world"
inner class InnerClass {
fun innerMethod() = [email protected]
}
//局部嵌套类
fun getName(): String {
class LocalNestedClass {
val name: String = "mytest"
}
var localNestedClass = LocalNestedClass()
return localNestedClass.name
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main10)
OutClass2().getName()
}
举一个综合的例子
class Person(val name: String, var age: Int) {
private inner class PersonFeature(var height: Int, var weight: Int) {
fun getPersonFeature() {
println("身高:$height,体重:$weight")
[email protected]()
}
}
private fun method() {
println("执行了Person的method方法")
}
fun getPerson() {
val personFeature = PersonFeature(120, 180)
personFeature.getPersonFeature()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main10)
val person =Person("zhangsan",20)
person.getPerson()
}
内部类PersonFeature会持有外部类Person的引用,所以内部类才能调用外部类的方法,通过 [email protected]()。
当外部类 、内部类、方法里面都可以定义成员变量,重名的时候该怎么处理?
class Person(val name: String, var age: Int) {
private val str: String = "Person属性"
private inner class PersonFeature(var height: Int, var weight: Int) {
private val str: String = "PersonFeature属性"
fun getPersonFeature() {
val str: String = "局部变量"
//1.访问外部类Person的str
println("${[email protected]}")
//2.访问当前内部类PersonFeature的str
println("${this.str}")
//访问局部变量的str
println("$str")
}
}
private fun method() {
println("执行了Person的method方法")
}
fun getPerson() {
val personFeature = PersonFeature(120, 180)
personFeature.getPersonFeature()
}
}
访问特定的一个作用域里面的成员变量。
Kotlin访问外部类变量的方式:[email protected]
Java访问外部类变量的方式:OutClas.this.str
再补充一点
class OutClass {
private val str: String = "hello world"
class NestedClass {
fun nestedMethod() = "welcome"
}
}
嵌套类相当于Java中的静态内部类,在Java中静态的只能访问静态的,不能访问非静态的。而非静态的是可以访问非静态和静态的。为什么会有这个规则呢?
原因是因为静态的并不属于当前类本身,而是属于当前的Class对象。
在Java中,NestedClass是静态的内部类,str是非静态的成员变量,显然是不能在静态的里面访问非静态的。所以在NestedClass里面是不可能访问到外部类OutClass里面定义的任何成员变量
那么对于嵌套类来说能访问什么?除了自己类里面定义的成员变量和方法之外,唯一能访问相同的外部类当中所定义的其他的嵌套类,因为他们都是静态的。
class OutClass {
private val str: String = "hello world"
class NestedClass {
fun nestedMethod() = "welcome"
}
class NestedClass2 {
var nestedClass = NestedClass()
}
}