相信有寫過 Java 的捧友應該對 OOP 不陌生,即使寫不出很漂亮的 OOP 架構(就是在說我...慚愧),至少也看過或聽過繼承、封裝、多型、抽象、以及還有很多很多的設計模式,這邊有一張圖可以大概的表示 OOP 知識框架
那 Kotlin 作為 Java 的後繼者,許多地方都與 Java 雷同,因此實作 OOP 也是沒有問題的,因此今天就要來了解一下 Kotlin 在實作 OOP 上和 Java 有哪些差異以及需要注意哪些問題
Kotlin 和多數語言一樣採用 class
定義類別
class doSomeThing {
// 建構子、邏輯、判斷...
}
Kotlin 中的類別成員有
在 Java 的 Class 中,Constructor 會長的像這樣
public class doSomeThing {
String s;
public doSomThing(String s) {
this.s = s;
}
}
但在 Kotlin 中, Class 的 Constructor 分成兩種
Primary Constructor 在 Class 中只會有一個,並會放在 class 後面,當作 class header 的一部份
// 括號中就是 Primary Constructor 區塊
class Person(var firstName: String, var lastName: String, var age: Int) {
// 建構子、邏輯、判斷...
}
在 Primary Constructor 區塊中不能寫邏輯,如果需要做初始化邏輯的部份可以交給 initializer blocks ,或是可以用來初始化宣告出來的變數
class Person(var firstName: String, var lastName: String, var age: Int) {
// 宣告變數的初始值是 Primary constructor 的 s
var firstName: String = firstName.toUpperCase()
// initializer blocks, 在 Constructor 後,第一個會被執行的區塊
init {
println("Primary constructor: ${age}")
}
}
Secondary Constructor 和 Primary Constructor 的差別是
Primary Constructor 在一個 Class 中只能有一個
Secondary Constructor 在一個 Class 中可以有多個
[color=orange]
Secondary Constructor 的寫法就會比較近似 Java 定義 Constructor 的方式,只是 Java 中使用的 Class name 換成 constructor
Example:
class Dog {
var host: mutableList<Person> = mutableListOf()
constructor(host: Person) {
this.host.add(host)
}
}
而 Primary 和 Secondary constructor 可以同時存在於 Class 中
但這時就要注意,如果已經存在 Primary constructor ,那之後創造的每個 Secondary constructor 都必須 Delegate Primary constructor
Example:
class Dog(val name: String) {
var host: mutableList<Person> = mutableListOf()
constructor(name: String, host: Person): this(name) {
this.host.add(host)
}
}
那上面有提到 Class 中可以撰寫 initializer blocks, 那麼這邊要注意在程式的實行順序會是依照:
因此在使用 Constructor 時,需要注意以上的狀況喔
在建立 Class 後可能會需要建立 Properties ,那在 Properties 可以分成 var
和 val
,那兩者個差別在前幾天變量介紹的時候就已經有探討過了,這邊快速複習一下
val : Read-only ,只能讀不能寫
var : Read and write, 可讀可寫
[color=orange]
那要定義成 var
或 val
就會根據需求而定,下面給了一個 Dog class 的範例,可以注意到
name
寫在 Primary constructor
裏面,因為我希望被實作時要先給狗狗的名稱,並且不能再重新給狗狗名稱,因為在我的世界裡是不允許棄養狗狗的!!!age
的變量是 var
,型態是 Int
,預設是 0host
的變量是 var
,型態是 List
,並且 List
中只能存 String
legs
的變量是 val
,型態是 Int
,並且預設值是4
,因為狗狗有四條腿// Dog.kt
class Dog(val name: String) {
var age: Int = 0
var host: MutableList<Person> = mutableListOf()
val legs: Int = 4
}
那在實作一隻叫 Bob
的狗時,首先我要先去實作 Dog class ,並給他 Bob 當作 Dog name
fun createDog() {
val mBob: Dog = Dog("Bob")
println(mBob.name) // Output: Bob
mBob.name = "Alice" // 這是不被允許的,因為 'name' 是 'val'
println(mBob.age) // Output: 0
mBob.age = 3
println(mBob.age) // Output: 3
println(mBob.host) // Output: []
mBob.host.add(Alice)
mBob.host.add(Charlie)
println(mBob.host.size) // Output: 2
}
另外,從這個例子還可以注意到,在使用 Properties 時並不用像 Java 需要寫 getter()
和 setter()
,因為 Kotlin 中的 Properties 會自帶 getter()
和 setter()
,因此這邊回顧上面 var 和 val ,就可以再補充一點
val : Read-only ,只能讀不能寫,因為只有
getter()
var : Read and write, 可讀可寫,因為有getter()
和setter()
[color=orange]
在 Class 中當然也可以寫 function 去增強 Class 的能力, Kotlin 的用法和 Java 的用法一樣,這邊直接給個範例,繼續給剛剛的 Dog class 吠叫和生日時增加歲數的 function
Example:
//
class Dog(val name: String) {
var age: Int = 0
var host: MutableList<String> = mutableListOf()
val legs: Int = 4
fun doRun() {
// 寫邏輯
}
fun doEat() {
// 寫邏輯
}
fun doSwim() {
// 寫邏輯
}
}
上面介紹了 Class ,不免俗的還是要介紹 Extends 和 Interface ,用法上和 Java 一樣,唯一有一個小差別是 Kotlin 不需要寫 extends
和 implements
關鍵字,而是用 :
代替 extends,這邊給個簡單 Java 和 Kotlin 的比較範例
extends class
interface
Java Example:
class A extends B implements C, D, E {
// ...
}
Kotlin Example:
class A : B(), C, D, E {
// ...
}
看起來不同,但架構上都是一樣的,因此在撰寫上只要簡單注意一下即可喔~
另外,在 java 中,除非開發者手動幫 class
加上 final
關鍵字,否則就被任意的繼承與改寫不是 final
的函式,這會導致子類別設計上可能會不符合父類別的設計初衷。而在 Kotlin 中改善了這個問題,在 Kotlin 中會預設 class 和裏面的函式是 final
,因此若要繼承 class 的話,必須加上 open
才能夠被繼承或重寫
Example:
class A : B() {
// ...
}
open B {
// ...
}
今天介紹了 OOP 中常見的 Class 、 Constructor 、 Properties 和 Extends ,其實大致上的觀念和其他支援 OOP 語言相差無幾,只有一些小改動,基本上只要實作過幾次,應該可以很快的接軌過去。明天會繼續介紹 OOP,將 Data class 、 Sealed class 、 Enum class 和 Object 等等項目介紹完,希望能在第 11 天時順利進到 App 的部份~
另外,今天我的系列文竟然被 『范聖佑』 大大注意到了,我看到訊息時,一整個驚嚇,也加入了 Kotlin 鐵人挑戰賽的群組,原本只是想說將這半年來學習的東西做一個紀錄和回顧,沒有完賽就算了。但現在有愈來愈多人在關注,讓我也鞭策自己要更努力把 30 天的文章寫出來,才不會辜負有在關注的好朋友們~