您的位置:首页 > 移动开发 > Android开发

Android开发,Kotlin的了解与学习(六)-----类与继承

2017-06-21 15:15 246 查看
前几章已经把kotlin最基本的语法、数据结构等说清楚了,接下来这两章主要讲解kotlin中关于类和接口的相关知识

类这个东西使用和java比较类似,最简单的如下

class innerClass {

}
再class之前可以加private protected internal 或者public,默认不写就是public了

另外需要注意的是,如果类的内部没有实体,可以直接这么写

class innerClass
不加括号

构造方法

提到类,肯定还会提到他的构造方法

kotlin中的构造方法和java有很大的不同,kotlin的构造方法分为两种:主构造方法、次构造方法

1.主构造方法:

class InnerClass constructor(name: String) {

}
是的,kotlin中的主构造方法,直接就属于类名的一部分,是直接放在类名之后的

constructor就是构造方法的意思,如果主构造方法中没有注解或者可见性修饰符的时候,constructor可以省略不写

class InnerClass(name: String){

}


同时,每个类都提供了一个初始化方法,用于在构造之后,进行初始化

如下:

class InnerClass constructor(name: String) {

var name: String? = null

init {
this.name = name
}

}


另外除了在init中使用,也可以在类本身中使用

class InnerClass constructor(name: String) {

var myName = name

}


除了在类体中初始化参数,还可以在构造方法的参数前加var或者val直接进行赋值

class InnerClass(var name: String) {

init {
println(name)
}

}


此时就相当于已经走了初始化、赋值两个步骤

2.次构造方法

次构造方法和java类似,是放在类里面的

class InnerClass{

constructor(name: String, age: Int){

}

}
此时是当不存在主构造方法时的写法

如果类存在主构造方法,就必须在次构造方法后调用this方法,将方法委托给主构造方法,即如果从次构造方法中进来后,还需要再次进入主构造方法

class InnerClass(name: String) {

constructor(name: String, age: Int) : this(name) {

}

}


次级构造方法可以有很多个,主构造方法只能存在一个

class InnerClass(name: String) {

constructor(name: String, age: Int) : this(name) {

}

constructor(name: String, age: Int, sex: String) : this(name, age) {

}

}


并且次级构造方法的this,不仅仅可以委托给主构造方法,像上面这样,也可以委托给其他的次级构造方法,只要保证最终会委托到主构造方法即可,像下面这样是不行的

class InnerClass(name: String) {

constructor(name: String, age: Int) : this(name, age, "") {

}

constructor(name: String, age: Int, sex: String) : this(name, age) {

}

}


两个次构造方法相互委托,会出现错误提示:There is a cycle in the delegation calls chain----委托调用链中有一个循环。

再来,我们可以看到在上面的代码中出现了三个name这参数,那么在初始化init的时候,我们调用name是指的哪一个呢?

很明显,指的是主构造方法

class InnerClass(name: String) {

constructor(name: String, age: Int) : this(name) {

}

constructor(name: String, age: Int, sex: String) : this(name, age) {

}

init {
println(name)//这个name指的是主构造方法中的name
}

}


那么如果主构造方法没有(后面会讲到并不是没有,其实是空),我们再使用name呢

class InnerClass{

constructor(name: String, age: Int) {

}

constructor(name: String, age: Int, sex: String) : this(name, age) {

}

init {
println(name)//这个是会报错的,找不到name
}

}


找不到name,即只有主构造方法中的参数是全局的

3.构造方法的可见性

如果像下面这样:

class InnerClass {

}
其实,他是相当于

class InnerClass constructor(){

}


也相当于

class InnerClass public constructor(){

}


默认是public的,这样我们在初始化的时候,可以这样

var inner = InnerClass()


那么,如果我们不想让我的类被其他类构造呢,比如我只能当父类,不允许其他类跳过子类直接构造呢?
那么就可以这样写

class InnerClass private constructor(){

}


这样,我们就不可以在其他地方构造这个类了

这一点,需要特别记住的

类的构造

刚刚,我们提到了,var inner = InnerClass()

这样的语句,这就是类的构建了,等同于java的

InnerClass inner = new InnerClass();


注意,Kotlin中是没有new的

其他的话,其实和java就没有多大区别呢,如果构造需要参数,直接传入就可以了

var inner = InnerClass(“name”)


类的继承

在kotlin中,类的继承和java差别还是挺大的
kotlin的继承使用的是“:”冒号,在kotlin里面,冒号的使用是非常频繁的,继承需要、定义需要、操作需要。

如下:

open class Person{

}

class Man : Person(){

}


这就是最简单的继承了,注意看里面的person这个类前面有一个open关键词,open在kotlin中代表了,这个类可以被继承,如果不写,其他类是无法继承该类的,这样的目的就是为了方便筛选出可继承类与不可继承类,因为在java中,如果一个类打出extends之后,会出现很多很多的类,有些类名字相似,你甚至不知道该继承哪一个,特别是在api的使用上。
然后就是复杂一点的用法:

open class Person(name: String, sex: String) {

}

class Man(name: String) : Person(name, "man") {

}


在继承的时候,如果父类有构造方法,子类必须完整的传入构造需要的参数去进行初始化

如果一个父类存在构造方法,并且子类并没有在主构造方法中进行构造,那么就需要在次构造方法中使用super关键字,委托给父类的构造方法

open class Person {

constructor(name: String) {

}

}

class Man : Person {

constructor(name: String) : super(name) {

}

}


同时,假如父类有多个构造方法,子类可以任意委托给其中一个

open class Person {

constructor(name: String) {

}

constructor(name: String, age : Int){

}

}

class Man : Person {

constructor(name: String) : super(name,0) {

}

}


方法的重写

子类重写父类的方法,和上面一样,也是需要在方法前加open关键字,默认修饰关键字为final

open class Person {

open fun fatherFoo(){

}

}

class Man : Person() {

override fun fatherFoo() {
super.fatherFoo()
}

}


如上,fatherFoo这个方法,如果想被子类重写,就需要在前面加上open关键字,同时,子类如果要重写父类的方法,就需要在方法前加上override这个关键字,不过这个关键字倒是不需要我们自己去写,在重写时,系统会自动添加上的。
至于里面的super,我就不说了,和java一样

再一个,如果此时有一个类,继承自Man这个类,那么此时fatherFoo这个方法默认就是可以被重写的,就不需要再添加open关键字,默认就是open

open class Person {

open fun fatherFoo(){

}

}

open class Man : Person() {

override fun fatherFoo() {
super.fatherFoo()
}

}

class Child : Man(){
override fun fatherFoo() {
super.fatherFoo()
}
}


那么,如果我们只想Man重写来自Person的方法,不允许Man的子类重写他父类的父类的方法,就需要在Man类的方法前加final关键字

final override fun fatherFoo() {
super.fatherFoo()
}


此时,Child就不允许重写该方法了,该操作也极大的利于我们限制最外层类触及里层类的方法。

抽象类

类的抽象,如下

abstract class Person {
abstract fun faFoo(): String

open fun getName() {
println(faFoo())
}
}


和java差不多,抽象类和抽象方法前加abstract即可

另外,子类可以使用抽象方法重写父类的一般方法

open class Person {
open fun getName() {

}
}

abstract class Man : Person() {
abstract override fun getName()
}


当然也不能瞎重写,父类的方法都没返回,你抽象方法也是没有返回的

最后提醒一点,抽象类,抽象方法,本来就拿给子类用的,所以,abstract修饰的方法、类,默认自带open

abstract class Person {//这里不需要open关键字,子类也可以继承
abstract fun getName()//这里也不需要open关键字,子类仍然可以重写
}

abstract class Man : Person() {
abstract override fun getName()
}


而这,就是kotlin无敌的人性化了。既然大家都知道这个东西的用法,我们就不再去写出来了

Android开发,Kotlin的了解与学习(七)-----接口与实现
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息