Kotlin系列之主構造方法和初始化語句塊
前面我們已經說過類和介面的知識點,今天來看看Kotlin中的主構造方法和初始化語句塊。
我們知道在Java中也存在構造方法
的概念,也有初始化塊
的概念。所以今天還是拿Kotlin和Java進行對比學習。
Java中的構造方法和初始化塊
在Java中構造方法有以下幾點的規則。
1 . 構造方法沒有返回值,方法名必須與類名相同
2 . 如果沒有顯式宣告構造方法,Java會給我們生成一個預設的不帶任何引數的構造方法
在Java中的初始化塊又分為普通初始化塊
和靜態初始化塊
,他們的規則如下。
1 . 普通初始化塊
在每次物件建立時被呼叫,靜態初始化塊
只在類被載入時呼叫,且只會被呼叫一次
2 . 普通初始化塊
用來在一個物件建立時初始化其中的一些引數
下面通過程式碼來簡單解釋以下上面的規則。
Java程式碼
package ja;
public class Main {
//靜態初始化程式碼塊
static {
System.out.println("類被載入了...");
}
private int value;
private int num;
//普通初始化程式碼塊
{
num = 10;
}
//構造方法用來初始化引數
public Main(int value ){
this.value = value;
}
public int add(int other){
return this.value + this.num + other;
}
}
上面都是java的基礎知識,寫出來主要是方便與Kotlin的進行對比。
Kotlin中的主構造方法和初始化語句塊
在Kotlin中也存在和Java中相似的概念,但也又一些差異。
這裡有一個概念是主構造方法
。在Kotlin中一個類同樣可以宣告多個構造方法,但Kotlin將他們分為主構造方法
和從構造方法
。
主構造方法
是一個主要且簡潔的初始化類的方法,而且它宣告在類的外部,而從構造方法
主構造方法
和與之相關的初始化語句塊
。
在Kotlin中構造方法的宣告需要使用到constructor
關鍵字,初始化語句塊的宣告需要使用到關鍵字init
。在Kotlin中構造方法一般是用於傳入一些建立類時需要的引數,配合初始化語句塊來對類的屬性進行初始化。下面用程式碼來實際說一下。
Kotlin程式碼
//該類的主構造方法需要傳入name引數
class User constructor(name: String){
//類的name屬性
val name: String
//初始化語句塊用於配合構造方法給屬性賦初始值
init {
this.name = name
}
}
上面的程式碼還是很好理解的,其實就相當於把我們的構造方法和類的宣告放在了一起。注意上面的this
和我們java中的用法是一樣的,都是在於構造方法的引數名和類的屬性名相同時來區分兩者。
當然Kotlin是一門追求簡潔的語言,我們可以把上面的程式碼進一步簡化。像下面這樣。
Kotlin程式碼
class User (name: String){
//類的name屬性
val name = name
}
直接省略了constructor
關鍵字和初始化語句塊,直接賦值即可。
當你覺得這樣已經夠簡潔的時候,還有更簡潔的,想下面這樣。
Kotlin程式碼
class User (val name: String)
直接將val
關鍵字載入構造方法屬性前面,就完成了構造方法引數的宣告和類屬性的宣告和賦值,甚至連{}
也不需要了。
Kotlin中的構造方法新特性
除了上面簡潔的語法,還有很多新特性。我們在前面的文章中說過,一個方法的引數可以又預設值,也可以在傳入方法引數時帶上引數名使程式碼可讀性更好。由於構造方法也是方法,我們同樣可以使用這些特性,就像下面程式碼描述的那樣。
Kotlin程式碼
//構造方法引數帶預設值
class User (val name: String, val isMan: Boolean = false)
那我們如何使用上面的類呢?
Kotlin程式碼
fun main(args: Array<String>){
//第二個引數使用了預設值
val user1 = User(name = "Mike")
val user2 = User(name = "Tom", isMan = true)
}
是不是程式碼簡潔清楚了很多呢。
Kotlin構造方法與繼承
我們知道在Java中如果我們沒有顯式宣告一個構造方法,就會為我們預設新增一個無參的構造方法,在Kotlin中也是一樣的。
那麼當我們涉及到繼承時,我們該怎麼寫呢?在Kotlin中當你繼承一個類不再只是寫出類名就可以了,而是要給你繼承類的構造方法同時傳入引數j將,就像下面這樣。
Kotlin程式碼
open class User (val name: String, val isMan: Boolean = false)
class GoogleUser(name: String, val age: Int): User(name){
}
上面的程式碼中,我們建立GoogleUser
這個子類,並且將它的構造方法的name引數傳遞給了父類的構造方法。同時我們還為子類增加了一個新的屬性age
。
當然,如果我們繼承的父類沒有指定構造方法,由於有預設構造方法的存在,我們在繼承時必須要注意。像下面的程式碼一樣。
Kotlin程式碼
open class Father
class Son: Father(){
//...
}
這裡我們在繼承father類時必須有()
,因為這裡的意義是構造方法。
我們前面也說過介面是沒有構造方法,不能被例項化的,所以就沒有()
,像下面這樣。
Kotlin程式碼
interface Clickable
class View: Clickable{
}
寫在最後
可以看出Kotlin在模仿Java的一些方面的同時,可以保證我們用更簡潔清楚和更少的程式碼來完成我們的工作。