嵌套類
嵌套類(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()
}
}