普通类(class)

80 阅读3分钟

一、类

1.1、定义类

可以使用如下代码定义一个类,以及声明它所拥有的字段和函数:

class Person {
    var name = ""
    var age = 0

    fun eat() {
        println(name + " is eating. He is " + age + " years old.")
    }
}

然后使用如下代码创建对象,并对对象进行操作:

fun main() {
    val p = Person()
    p.name = "Jack"
    p.age = 19
    p.eat()
}

和java实例化方式类似,只是去掉类new关键字,之所以这么设计,是因为当你调用了某个类的构造函数时,你的意图只可能是对这个类的实例化。

1.2、继承

Kotlin中一个类默认是不可以被继承的,如果想要让一个类可以被继承,需要主动声明open关键字:

open class Person {
    var name = ""
    var age = 0

    fun eat() {
        println(name + " is eating. He is " + age + " years old.")
    }
}

要让另一个类去继承Person类,则需要使用冒号关键字:

class Student : Person() {
    var sno = ""
    var grade = 0
}

为什么Person类后面要加上一对括号呢?

这就牵扯到了Java继承特性中的一个规定:子类中的构造函数必须调用父类中的构造函数

这个规定在Kotlin中也要遵守。

那么再来回头看一下Student类,现在我们声明了一个主构造函数,根据继承特性的规定,子类的构造函数必须得调用父类的构造函数,可是主构造函数并没有函数体,我们怎样去调用父类的构造函数呢?

有的朋友可能会说,在init结构体当中去调用不就好了,这或许是一种办法,但却绝对不是一种好办法,因为绝大多数的场景我们都是不需要编写init结构体的。

Kotlin当然没有采用这种设计,而是用了另外一种简单但是可能不太好理解的设计方式:括号。子类的主构造函数调用父类中的哪个构造函数,通过在父类的后面加上括号来指定。

class Student(val sno: String, val grade: Int) : Person() {
}

在这里,Person类后面的一对空括号表示Student类的主构造函数在初始化的时候会调用Person类的无参数构造函数,即使在无参数的情况下,这对括号也不能省略。

二、接口

Java是单继承结构的语言,任何一个类最多只能继承一个父类,但可以实现任意多个接口,kotlin也是如此,Kotlin中定义接口的关键字和Java中是相同的,都是使用的interface:

interface Study {
    fun readBooks()
    fun doHomework()
}

而Kotlin中实现接口的关键字变成了冒号,和继承使用的是同样的关键字:

class Student(val name: String, val age: Int) : Person(name, age), Study {
    override fun readBooks() {
        println(name + " is reading.")
    }

    override fun doHomework() {
        println(name + " is doing homework.")
    }
}

和Java不同的是,Kotlin 的接口中定义的函数可以进行默认实现(Java 1.8之后也支持这个功能)

interface Study {
    fun readBooks()
    fun doHomework(){
		println("do homework default implementation.")
	}
}

三、修饰符

private:对当前类内部可见。 public:与Java一致,表示对所有类可见,但在Kotlin中,public修饰符是默认项。而在Java中,default是默认项。 protected:Java中表示对当前类,子类和同一包路径下的类可见,在Kotlin中表示只对当前类和子类可见。 internal:Kotlin抛弃了Java中的default(同一包路径下的类可见),引入了internal,只对同一模块中的类可见。

修饰符JavaKotlin
public所有类可见所有类可见(默认)
private当前类可见当前类可见
protected当前类,子类,同一包路径下类可见当前类,子类可见
default同一包路径下类可见(默认)
internal同一模块中的类可见