- 一、类
- 1.1 类的声明
- 1.2 构造函数
- 1.3 类实例的创建
- 1.4 类成员的组成
- 二、继承
- 2.1. 构造
- 2.2 方法的覆盖
- 2.3 属性的覆盖
- 2.4 抽象类
- 2.5 伴生对象
一、类
1.1 类的声明
- 类使用
class
关键字声明- Kotlin中的类,默认都是
public final
类型的;
class Parent {}
class Children //如果类中没有类体,则花括号可以省略
// ---------- 编译后的字节码如下 ------------
public final class Parent {}
public final class Children {}
1.2 构造函数
在Kotlin中,可以有一个主构造函数和多个次构造函数,主构造函数在类头;
主构造函数 & 次构造函数
// 1.如果主构造函数中没有任何 "注解" 或 "可见性修饰符",则 constructor 关键字可以省略
class Parent constructor(name: String) {}
class Parent(name: String) {}
// 有修饰符,注解; constructor不能省略
class Parent public @Inject constructor(name: String) {}
/*
* 2.在Java中,构造方法中可以进行代码初始化;
* Kotlin中,主构造函数中不能包含任何代码,但是提供了init{...}方法体
*/
class Parent(name: String) {
val name: String
init{ // 主构造的参数可以直接在初始化块 init 中使用
= name
}
}
/*
* 3.主构造方法中的参数,可以在初始化块init中使用,也可以在类体中声明的属性初始化器中使用;
*
*/
class Parent(name: String) {
//var name: String = name.toUpperCase() //在属性初始化器中使用主构造参数
val name: String
init{
= name //在初始化块init中使用主构造参数
}
}
// 在主构造函数中,使用 val 或者 var 声明类中的属性和主构造函数中的属性,在类中任何地方都可以使用
class Parent(val name: String) {
init {
print("name = $name")
}
fun test() {
print("name = $name")
}
}
/*
* 4. 如果类有主构造函数,每个次构造函数需要委托给主构造函数;
* 1)可以直接委托,也可以通过其他次构造函数间接委托;
* 2)委托到通一个类的另一个构造函数使用 this 即可;
*/
class Parent(name: String) {
var name: String
var age: Int? = null
init {
= name
}
constructor(name: String, age: Int): this(name) {// 使用this指引到主构造
this.age = age
}
}
// 5.如果主构造函数的所有参数都有默认值,则编译器会生成一个额外的无参构造(默认构造)
class Parent constructor(name: String = "Elson") {
1.3 类实例的创建
val parent = Parent("Elson") //没有Java中的new关键字
1.4 类成员的组成
- 构造函数
- 初始化块
- 函数
- 属性
- 嵌套类和内部类
- 对象声明
二、继承
在Java中,所有类的默认超类是
super
;
在Kotlin中,所有类的默认超类是Any
,该类只有toString()、equals()、hashCode()
三个方法;
2.1. 构造
- 子类中含有主构造函数
open class Parent(name: String):AnkoLogger {
var name: String
var age: Int? = null
init {
= name
info("parent ... init ")
}
constructor(name: String, age: Int):this(name) {
this.age = age
info("parent ... constructor ")
}
}
// 子类有主构造函数时,则其每个次要构造函数必须使用 super 关键字初始化其基类;或者委托给另一个构造函数执行;
class Child(name: String): Parent(name) {
private var sex: String?=null
// 这里使用 this 调用主构造函数进行初始化
constructor(name: String, age: Int) : this(name) {
this.age = age
info("child ... constructor ")
}
// 这里使用 this 间接调用(先调用次要构造,后调用主构造)主构造函数进行初始化
constructor(name: String, age: Int, sex: String) : this(name, age) {
this.sex = sex
info("child ... constructor ")
}
init {
info("child ... init")
}
}
- 子类中不含有主构造函数
// class类默认是final类型的,不能被继承,所以需要使用 open 关键字让父类可以被继承;
open class Parent(name: String):AnkoLogger {
var name: String
var age: Int? = null
init {
= name
info("parent ... init ")
}
constructor(name: String, age: Int):this(name) {
this.age = age
info("parent ... constructor ")
}
}
// 没有主构造函数,则其每个次要构造函数必须使用 super 关键字初始化其基类;或者委托给另一个构造函数执行;
class Child: Parent {
private var sex: String?=null
// 这里可以直接调super(name, age),当前是作演示,所以调用super(name);
constructor(name: String, age: Int) : super(name) {
this.age = age
info("child ... constructor ")
}
constructor(name: String, age: Int, sex: String) : super(name, age) {
this.sex = sex
info("child ... constructor ")
}
init {
info("child ... init")
}
}
执行代码:Child(“name”, 18, “M”)
打印结果:
parent … init
parent … constructor
child … init
child … constructor
2.2 方法的覆盖
关键字:
open 、override
open class Paren(name: String): AnkoLogger {
var name: String
init {
= name
}
// 通过 open 关键字使方法可以被子类重写
open fun play() {
info("parsent name = $name")
}
}
class Child(name: String): Parent(name) {
// 通过 override 关键字重写父类方法
override fun play() {
//super.play()
info("child name = $name")
}
}
2.3 属性的覆盖
属性覆盖和方法覆盖类似,可以用
var
属性覆盖一个val
属性,反之则不行;
关键字:open 、override
open class Parent {
open val name: String get {...}
}
class Child: Parent() {
override val name : String = ...
}
2.4 抽象类
可以使用一个抽象的成员覆盖一个非抽象的
open
成员
open class Parent {
open fun play() {}
}
abstract class Child : Parent() {
override abstract fun play()
}
2.5 伴生对象
Kotlin中没有静态方法,伴生对象可以实现同样的效果,通过 类名.方法名() 调用;