最近在学习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
至目前为止还是没有找到比较权威的和官方的解释和说明,希望有大牛看到之后,有相关的信息可以告知一升。