1. 定义一个类
熟悉 Java 的我们都知道,定义一个类很简单:
public class Foo{
private Bar bar;
public void foobar(){
...
}
}
那么在 Kotlin 中我们是这样定义的:
class Foo{
val bar : Bar = Bar()
fun foobar(){
....
}
}
不难看出,其实两者很类似,也是有一点的不同:
- Java 代码中对象的属性没有初始化,而 Kotlin 中的属性进行了初始化(在 Kotlin 中除非显示声明延迟初始化,否则都需要给一个默认值。)
- 在初始化对象的时候,我们没有使用 new 关键词来创建对象,而是直接使用
Bar()
,没错,Kotlin 取消了 new 。 - Java 代码中使用 public/private 等修饰符,指定了访问域,而 Kotlin 类中没有指定(Kotlin 默认全局可见,类似 Java的public)
2. 定义接口
这里的定义和 Java 基本没有区别,在 Java8 之后,我们接口里面的方法可以有一个默认实现:
interface Foo{
default void bar(){
// doSomething
}
}
Kotlin 同样支持,甚至还支持抽象属性,这里局特别像抽象类了
interface Foo{
val foobar : Foobar //抽象属性
fun bar(){
// doSomething
}
}
3. 进阶
3.1 构造函数默认参数
我们在 Java 的学习/工作中,通常创建对象的时候,会有直接使用默认值的情况,比如我们就以常见的 Student 来说,Student 有年龄,身高 等个属性,下面我们来构建一下 Java 代码
public class Student {
private int age;
private double height;
private String name;
public Student(int age, double height,String name) {
this.age = age;
this.height = height;
this.name = name;
}
public Student(int age) {
this.age = age;
}
public Student(double height) {
this.height = height;
}
}
在 IDEA 中我们可能只需要写完几个属性,然后通过快捷键,就可以方便的创建构造函数。而在 Kotlin 中,我们只需要这样定义:
class Student(val age:Int = 0,val height:Double = 0.00,val name:String? = null)
这么看是不是一下省了好多代码(KPI 又少了上千行代码量了)
神奇的还不知是这样,还记得我们怎么创建对象的吗?
val student:Student = Student() // 这里创建的对象完全使用默认值 ==>> age=0,height=0.00,name=null
val student:Student = Student(age = 18) // ==>> age=18,height=0.00,name=null
val student:Student = Student(height = 180.00) // ==>> age=0,height=180.00,name=null
val student3:Student = Student(12,12.0,"xiaohong") // ==>> age=0,height=180.00,name=xiaohong
值得注意的是这里的属性顺序一定要按照对应的类型,如果我们省略掉部分属性,则可能存在下面问题
3.2 init 语句
Kotlin 引入init 代码块,其使用方式类似 Java 的静态代码块,但此处说明,init 语句块并不是静态代码块,这里只是用来初始化构造方法里面的属性值的,还是以上述 Student 为例 ,我们可以这样定义:
class Student(val age:Int = 0,val height:Double = 0.00,val name :String? = null){
init {
println(name)
}
}
在初始化的时候就会打印name 字段。
所以在 init 代码块中,我们可以根据属性的值去做一些操作。init 语句块是可以有多个的,而且执行的顺序也是哪找从上到下来执行。也就是说可以像这样的写法
init{
// doPartOne
}
init{
// doPartTwo
}
3.3 延迟初始化
在前面我们说了 val 声明的对象,需要显示的创建对象,除非指定了延迟初始化,那么我们来看下,如何延迟初始化。
在 Kotlin 中我们有两种方式延迟初始化,一种是 by lazy{}
, 一种是lateinit
修饰
by lazy
我们还是以 Student 为例:
class Student(val age:Int = 0,val height:Double = 0.00,val name :String? = null){
val sex : String by lazy{
"male"
}
}
lateinit
class Student(val age:Int = 0,val height:Double = 0.00,val name :String? = null){
lateinit var sex :String
}
延迟初始化的意义在于只有在首次调用的时候才去进行赋值操作,这两者的区别是
- by lazy 用于 val 声明的变量
- lateinit 用于 var 声明的变量
3.4 主从构造函数
Kotlin 中有一个主构造函数,以及一个或多个次构造函数。他们都是用constructor来修饰,当然,如果这个构造函数是可见的,或者没有任何修饰符的,可以省略关键字。还是以上述 Student 为例:
class Student constructor(val age:Int = 0,val height:Double = 0.00,val name :String? = null)
// 因为没有修饰符,可以直接省略成我们之前声明的那样
class Student (val age:Int = 0,val height:Double = 0.00,val name :String? = null)
主构造函数不能含有任何代码,相关初始化的操作都交给 init 语句块执行
次构造函数的声明如下:
class Student(val age:Int = 0,val height:Double = 0.00,val name :String? = null){
constructor(sex:String) : this()
}
这里我们注意到,我们调用了 this(),这里是调用了主构造器。所以当我们声明次构造器的时候,最后要指定到主构造函数,这有点主从的关系。
从事Android 开发的朋友我们都知道自定义 View,在自定义 view 的时候,我们指导 view 的构造方法有好几个,所以在这种情况之下,我们就可以使用 次构造函数来做,例如
class CustomView: View {
constructor(context:Context) :this(context,null){ }
constructor(context: Context,attributeSet: AttributeSet?):this(context,attributeSet,0)
constructor(context: Context,attributeSet: AttributeSet?,defStyle: Int):super(context,attributeSet,defStyle)
}
3.4 JavaBean
在 日常开发中,我们会创建很多 bean 对象,其写法大多如下
public class Student {
private int age;
private double height;
private String Name;
public Student(int age, double height, String name) {
this.age = age;
this.height = height;
Name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getHeight() {
return height;
}
public void setHeight(double height) {
this.height = height;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
@Override
public boolean equals(Object o) {
...
}
@Override
public int hashCode() {
...
}
}
如今使用 IDEA使用快捷键生成确实很快,但是 Kotlin 给了我们一个数据类data class
上述代码只需要写成:
data class Student(val age:Int = 0,val height:Double = 0.00,val name :String? = null)
Kotlin 会自动帮我们做好 setter/getter /equals/hashCode/toString 等方法。