本章内容包括:
- 类的基本要素
- 类的继承结构
- 可见性修饰符
- 接口
0. 前言
在上一篇的末尾,我们提到了Kotlin的包和导入。
原本我是准备把这篇的内容也放在上一篇的,但是后来一想,这张的内容会很有点多,放进去的话可能会导致上一篇太大了,所以就单独分成一篇了。
在说类之前,我们先来看下一个类的Java版和Kotlin版的对比,这个会一下子就让你对Kotlin感兴趣。
我们现在有一个需求,需要定义一个JavaBean类Person,这个类中包含这个人的姓名、电话号码以及地址。
我们先来看下Java的实现:
public class Person {
private String firstName;
private String lastName;
private String telephone;
private String address;
public Person(String firstName, String lastName, String telephone, String address) {
this.firstName = firstName;
this.lastName = lastName;
this.telephone = telephone;
this.address = address;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
这是一个很基本的Java类,我们定义了四个private属性,然后给定了一个构造函数,然后对每个属性都给了get和set方法。
相信大家学Java一定都写过这个类。但是我们想想,就写一个功能这么简单的类,Java却需要我们写这么多内容,有的同学会说:Idea和Eclipse都不是提供了自动生成代码的工具吗。但是如果你看了Kotlin的实现,一定会觉得连自动生成工具都麻烦:
class Person(
val firstName: String,
val lastName: String,
val telephone: String,
val address: String
)
对,你没有看错,Kotlin的类就是这么的简单:
-
由于Kotlin的属性默认的修饰符就是
public
。但是由于我们这个方法设置成了val
,所以除了构造方法外,没法对这个属性的值进行更改。但是从Kotlin编译后会自动将val
的属性转为private final String firstName;
,var
的属性转为private String firstName;
-
由于Kotlin会自动为属性生成
get
和set
方法,所以没必要去显式的写get
和set
方法,除非你需要自定义的get
和set
方法。但是由于这个类的属性都是val
,所以只会生成get
方法。 -
Kotlin的默认构造方法是直接写在类名后面的
接下来我们就把这个代码进行分解,逐步来讲解Kotlin的类。
1. 类与继承
1.1 类
与Java类似,Kotlin也是使用class
关键字来表示类。
class Person() {
}
类声明由类名、类头(指定其类型参数、主构造函数等)以及由花括号包围的类体构成。类头和类体都是可选的,一个类如果没有类体,可以省略花括号:
class Person()
1.2 构造函数
1.2.1 主构造函数
Kotlin的一个类可以有一个主构造函数以及一个或者多个次构造函数。主构造函数是类头的一部分,跟在类名之后:
class Person constructor(val name: String){
}
如果主构造函数没有任何注解或者可见性修饰符,可以省略这个constructor
关键字。
class Person(val name: String){
}
主构造方法主要有两种目的:表明构造方法的参数,以及定义使用这些参数初始化的属性。
但是主构造方法不允许直接有代码块,所以如果需要在主构造方法中添加初始化代码,可以放到init关键字的代码块中:
class Person(val _name: String) {
val name: String
init {
name = _name
println(name)
}
}
但是同时,这个例子中,_name赋值给name,这个语句可以放在name的定义中去,所以可以改成:
class Person(val _name: String) {
val name: = _name
init {
println(name)
}
}
但是,如果主构造方法需要添加注解或者修饰符的话,这个constructor
是不能省略的:
class Person private constructor(val name: String) {
}
1.2.2 次构造函数
类也可以单纯的声明次构造方法而不声明主构造方法:
class Person {
val name: String
constructor(_name: String) {
name = _name
println(name)
}
}
如果类有一个主构造函数,每个次构造函数需要委托给主构造函数, 可以直接委托或者通过别的次构造函数间接委托。委托到同一个类的另一个构造函数用 this 关键字即可: