關於學習Kotlin子類繼承父類,成員屬性Override時候需要注意的問題
最近在學習Kotlin這門語言,作為一個java程式設計師兼android程式設計師,Kotlin又在17年強勢被google推崇為android官方開發語言之一,這就意味著,過去基於java語言的android開發人員,很有必要去掌握Kotlin這門語言,當然我這裡不去談論Kotlin如何,今天這個部落格主要就是記錄一下在學習Kotlin【繼承-覆蓋】這一節的時候遇到的一個特性,想做個記錄,記錄的主要原因是我今天遇到的這個問題,在很多入門學習帖子和部落格都沒有提及到這個特性。
首先,我們先宣告一個基類:
package zhg.extend.demo open class Person{ open var nickname:String?=null get() =field?:"二狗子" set(value){ field = value } open var name:String?=null get() =field?:"無名英雄" set(value){ field = value } open var age:Int=0 get() =field set(value){ field = value } constructor(name:String?,age:Int){ this.age = age this.name = name } constructor(name:String?,age:Int,nickname:String?):this(name,age){ this.nickname = nickname } open fun say(){ println("Hello! my name is ${this.name} , i'm ${this.age} years old, my nickname is ${this.nickname}") } }
很明顯,基類Person中的成員都被宣告為open,基類本身也被修飾為open,說明這個基類是可以被繼承的,其成員都是可以被Override的(至於為什麼要用open來修飾,以及其他基礎地方就不再複述了)。
OK,很簡單,我們直接去繼承Person,覆蓋他的成員屬性和函式,如下:
package zhg.extend.demo; class Student : Person { override var nickname:String?=null override var name:String?=null override var age:Int=0 constructor(name: String?, age: Int) : super(name, age) { } constructor(name: String?, age: Int, nickname: String?) : super(name, age,nickname) { } override fun say() { println("Hello! my name is ${this.name} , i'm ${this.age} years old, my nickname is ${this.nickname}") } } fun main(args: Array<String>) { var student = Student( "太平公主",20,"唐朝公主") student.say() }
上面的程式碼很簡單,直接繼承了Person這個類,成員屬性和函式都Override了,可以看到成員屬性和函式都使用override來修飾了。
我們在main方法裡面測試,看到的結果是
Hello! my name is 太平公主 , i'm 20 years old, my nickname is 唐朝公主
當然這是我想看到結果,但是在這之前,我的程式碼和前面貼出的程式碼有一個非常非常細微的差別,程式碼如下:
package zhg.extend.demo
open class Person{
open var nickname:String?=null
get() =field?:"二狗子"
set(value){
field = value
}
open var name:String?=null
get() =field?:"無名英雄"
set(value){
field = value
}
open var age:Int? =0
get() =field?.toInt()?:100
set(value){
field = value
}
constructor(name:String?,age:Int?){
this.age = age
this.name = name
}
constructor(name:String?,age:Int?,nickname:String?):this(name,age){
this.nickname = nickname
}
open fun say(){
println("Hello! my name is ${this.name} , i'm ${this.age} years old, my nickname is ${this.nickname}")
}
}
package zhg.extend.demo;
class Student : Person {
override var nickname:String?=null
override var name:String?=null
override var age:Int?=0
constructor(name: String?, age: Int?) : super(name, age) {
}
constructor(name: String?, age: Int?, nickname: String?) : super(name, age,nickname) {
}
override fun say() {
println("Hello! my name is ${this.name} , i'm ${this.age} years old, my nickname is ${this.nickname}")
}
}
fun main(args: Array<String>) {
var student = Student( "太平公主",20,"唐朝公主")
student.say()
}
我列印的結果一直是
Hello! my name is 太平公主 , i'm 0 years old, my nickname is 唐朝公主
你會覺得很奇怪,為什麼只有age這個屬性沒有打印出20?
查閱了相關官方文件和一些國內一些部落格和帖子都沒說出這兩種寫法的區別。
然後後面還發先,在上面的程式碼基礎上,將子類Student中的age屬性寫成如下方式,賦初值為null,就能達到理想的結果。
override var age:Int?=null
至目前為止還是沒有找到比較權威的和官方的解釋和說明,希望有大牛看到之後,有相關的資訊可以告知一升。