您的位置:首页 > 其它

Kotlin基础教程-类与继承

2017-06-01 00:15 405 查看
Classes and Inheritance

关键字:class

class Doctorq {}


构造方法

一个类有一个主构造器,多个副构造器。主构造器是类头部的一部分,紧跟类名后面。

主构造器

class Person constructor(firstName: String) {
}


如果主构造器没有任何注解和访问修饰符,可以省略关键字
constructor


class Person(firstName: String) {
}


主构造器不能包含任何代码,如果需要在主构造器中执行代码,可以使用
init
关键字定义初始化代码:

class Customer(name: String) {
init {
logger.info("Customer initialized with value ${name}")
}
}


其中可以在初始化代码块中使用主构造器中传入的参数,也可以在类
body
体中使用该参数:

class Customer(name: String) {
val customerKey = name.toUpperCase()
}


定义类属性的简洁方式如下

class Person(val firstName: String, val lastName: String, var age: Int) {

}


主构造中的参数可以是
var
也可以是
val


如果主构造器含有注解或者访问修饰符,则必须加
constructor
:

class Customer public @Inject constructor(name: String) { ... }


副构造器

副构造器在类内部,用
constructor
定义:

class Person {
constructor(parent: Person) {
parent.children.add(this)
}
}


如果既有主构造器,也有副构造器,那么副构造器需要委托给主构造器,同一个类中访问其他构造器,需要使用关键字
this


class Person(val name: String) {
constructor(name: String, parent: Person) : this(name) {
parent.children.add(this)
}
}


如果一个非抽象类没有定义任何构造器,会自动生成一个无参数的主构造器,可见性为
public
,如果你不想构造器可见,你可以显式定义个主构造器,访问修饰符用
private


class DontCreateMe private constructor () {
}


提示:如果主构造器的参数都有默认值,JVM编译器就会默认生成一个无参数的构造器,这会让创建对象变的很方便,无需传入参数。

class Customer(val customerName: String = "")


创建类实例

kotlin中创建实例不需要使用
new
关键字:

val invoice = Invoice()

val customer = Customer("Joe Smith")


类成员

构造器,初始化代码块

函数

属性

嵌套类和内部类

object定义

继承

kotlin中的所有类都继承一个父类
Any
,无需声明自动继承。

Any除了含有
equals()
hashCode()
,
toString()
三个函数外,就没有任何其他成员了。

如果想显式定义个超类,在类的头部用冒号(:)+父类名:

open class Base(p: Int)

class Derived(p: Int) : Base(p)


open关键字类似java中的final的反义词,而且默认所有的类都是final的

如果子类含有主构造器,基础类也必须在此处进行初始化,将子类的主构造器中的参数传递给父类的主构造器。

如果子类没有主构造器,那么每个副构造器都要使用
super
关键字初始化父类,也可以调用已经初始化父类的其他的副构造器。

class MyView : View {
constructor(ctx: Context) : super(ctx)

constructor(ctx: Context, attrs: AttributeSet) : super(ctx, attrs)
}


重写

关键字override

方法重写

open class Base {
open fun v() {}
fun nv() {}
}
class Derived() : Base() {
override fun v() {}
}


上面子类重写了父类的v函数,必须使用
override
关键字注解,否则编译器就会报错。但是如果没有用open定义的父类函数,不可以重写,默认是final是无法被重写的。

final
定义的类中,
open
方法也是无法被重写的。

如果你不想被继承者重写,你也可以加上
final
标识

open class AnotherDerived() : Base() {
final override fun v() {}
}


属性重写

open class Foo {
open val x: Int get { ... }
}

class Bar1 : Foo() {
override val x: Int = ...
}


上面的代码有点神奇的地方是
val
定义的属性也能被重写,神奇啊。实际上重写
val
的调用的是
getter
方法,重写
var
调用的是
setter
方法。

你也可以使用
override
标识主构造器中的参数。

重写规则

如果继承多个接口,而且接口中的成员函数和父类的成员函数一样,你必须重写接口中的成员函数,为了区分重写的是哪个接口或者父类的函数,需要用
super<类名/接口名>
,如下:

open class A {
open fun f() { print("A") }
fun a() { print("a") }
}

interface B {
fun f() { print("B") } // interface members are 'open' by default
fun b() { print("b") }
}

class C() : A(), B {
// The compiler requires f() to be overridden:
override fun f() {
super<A>.f() // call to A.f()
super<B>.f() // call to B.f()
}
}


抽象类

含有抽象成员的类成为抽象类

抽象类中抽象成员没有具体实现,我们还可以用抽象函数来重写一个非抽象的,open的父类成员。

open class Base {
open fun f() {}
}

abstract class Derived : Base() {
override abstract fun f()
}


伴生对象

kotlin中没有静态成员变量的概念,如果你不想通过类实例访问某个成员,可以使用伴生对象
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: