kotlin為聲明類 比 swift 中更為簡潔
// swift
class Dog {
// 屬性
var name: String
var weight: Int
init(name: String, weight: Int) {
self.name = name
self.weight = weight
}
}
Kotlin 寫法,直接將屬性定義在構(gòu)造器中
// kotlin
class Dog(val name: String, var weight: Int) {}
// 等價于
class Dog(name: String, weight: Int) {
val name = name
var weight = weight
}
另外 需要在構(gòu)造器中使用 val | var 對屬性進(jìn)行定義, val 定義的屬性,賦值后就不能再改變, 即 屬性只讀
var dog = Dog("Lisa", 20)
dog.weight = 30 // weight 屬性使用 var聲明 賦值后可以更改
dog.name = "Doge" // Error 使用 val聲明 不能進(jìn)行更改
初始化塊(initializer block)
和其它語言不通,在對象 構(gòu)造(constructor) 完之后,如果你想做一些復(fù)雜的操作,比如加載數(shù)據(jù)等,可以使用 init 執(zhí)行一些額外的操作
class Dog(val name: String, var weight: Int) {
// 可以定義多個 init blocks
// 執(zhí)行順序按照其定義的順序
init {
println("the first init block")
}
init {
println("the second init block")
}
}
Getter and Setter
類中每一個使用 var 聲明的屬性都有默認(rèn)的賦一個getter和setter, 而使用 val 聲明的屬性,則只會給一個getter
var someProperty: String
get() = field
set(value) {
field = value
}
val readOnlyProperty: String
get() = field
示例:
// swift
class Point {
var x = 0.0, y = 0.0
}
class Size {
var width = 0.0, height = 0.0
}
class Rect {
var origin = Point()
var size = Size()
var center: Point {
get {
let centerX = origin.x + (size.width / 2)
let centerY = origin.y + (size.height / 2)
return Point(centerX, centerY)
}
set(newCenter) {
// 根據(jù)新的中心點(diǎn) 推斷出 原點(diǎn)的位置
origin.x = newCenter - (size.width / 2)
origin.y = newCenter - (size.height / 2)
}
}
}
kotlin 版本:
// kotlin
class Point(var x: Double = 0.0, var y: Double = 0.0) {}
class Size(var width: Double = 0.0, var height: Double = 0.0) {}
class Rect(var origin: Point = Point(), var size: Size = Size()) {
var center: Point
get() {
val centerX = origin.x + (size.width / 2)
val centerY = origin.y + (size.height / 2)
return Point(centerX, centerY)
}
set(value) {
// 根據(jù)新的中心點(diǎn) 推斷出 原點(diǎn)的位置
origin.x = value - (size.width / 2)
origin.y = value - (size.height / 2)
}
}
另外一例:
// kotlin
class Dog(val name: String, var weight_param: Int) {
var weight = weight_param
set(value) {
// 注意這里的 field 標(biāo)識符
if (value > 0) field = value
}
var weightInKgs: Double
// 此處get的寫法 如果body只有一句 可以直接=
get() = weight / 2.2
}
其中:
- setter 中
field表示向前引用屬性
類的繼承
和其它語言不通之處
- 子類繼承時,父類需要完成構(gòu)造
這個感覺有點(diǎn)怪怪的,和其它語言有點(diǎn)差別,以swift舉例:
// Swift
// 父類
class Car {
let make: Int
let model: String
init(make: Int, model: String) {
self.make = make
self.model = model
}
func move() {
print("A car is moving")
}
}
// 子類 敞篷車
class ConvertibleCar: Car {
override func move() {
print("A convertible car is moving")
}
}
let myCar = COnvertibleCar(make: 1990, model: "WorksWagen")
myCar.move()
在kotlin中,
// kotlin
open class Car(open val make: Int, open val model: String) {
open fun move() {
println("a car is moving")
}
}
// 父類調(diào)用構(gòu)造器
class ConvertibleCar(override val make: Int, override val model: String): Car(make, model) {
override fun move() {
println("a convertible car is moving")
}
}
val myCar = ConvertibleCar(1990, "WorksWagen")
myCar.move()
因為kotlin構(gòu)造器中的參數(shù),實際上屬性,繼承時要確保父類中的屬性初始化完成(個人覺得寫法有點(diǎn)別扭??)
- 訪問修飾符
kotlin中類和屬性,默認(rèn)修飾符為 final, 如果想要被繼承,屬性想被override,則需要將修飾限定符修改為 open
// kotlin
// Car需要被繼承 則需要使用 open 進(jìn)行修飾 默認(rèn)是 final
// make, model 屬性希望被 override, 則需要 open進(jìn)行修飾
open class Car(open val make: Int, open val model: String) {
// 子類不能 override 這個方法
fun bark() {
println("bark ...")
}
open fun move() {
println("a car is moving")
}
}
//
class ConvertibleCar(override val make: Int, override val model: String): Car(make, model) {
override fun move() {
println("a convertible car is moving")
}
}
val myCar = ConvertibleCar(1990, "WorksWagen")
myCar.move()
- var 和 val 修飾的屬性
在繼承關(guān)系中,如果在父類中使用 val 聲明的屬性,如果需要修改,則需要使用 override 關(guān)鍵詞,如果使用 var 修飾的屬性,則可以在 init block 中進(jìn)行修改
// val 修飾
open class Car(open val make: Int, open val model: String) {
open val image = "" // 車的圖片
fun bark() {
println("bark ...")
}
open fun move() {
println("a car is moving")
}
}
class ConvertibleCar(override val make: Int, override val model: String): Car(make, model) {
// 需要使用override對父類中的屬性進(jìn)行修改
override val image: String = "convertibleCar.jpg"
override fun move() {
println("a convertible car is moving")
}
}
// 使用var 修飾
open class Car(open val make: Int, open val model: String) {
// open 也可以省略
var image = "" // 車的圖片
fun bark() {
println("bark ...")
}
open fun move() {
println("a car is moving")
}
}
class ConvertibleCar(override val make: Int, override val model: String): Car(make, model) {
// 在 initializer block 中對父類屬性進(jìn)行修改
init {
image = "convertibleCar.jpg"
}
override fun move() {
println("a convertible car is moving")
}
}
另外 父類中使用 val 聲明的屬性,子類中可以使用 var 進(jìn)行override; 但是父類中使用 var 聲明的屬性,子類中不能使用 val 進(jìn)行override
open class Animal {
open val name: String = ""
}
class Dog: Animal() {
// 使用 var 對父類中的name 進(jìn)行修改
// 本質(zhì)上是在父類屬性的基礎(chǔ)上添加了一個setter 對屬性進(jìn)行了擴(kuò)充
override var name = "lily"
}
抽象類
當(dāng)一個類使用 abstract 聲明為抽象類時,不需要使用 open 進(jìn)行修飾.
abstract class Animal {}
kotlin中的抽象類和其他語言基本類似,抽象類可以擁有抽象屬性和抽象方法,子類必須對抽象類中定義的抽象屬性和方法給出實現(xiàn)
abstract class Animal {
abstract val image: String
abstract val food: String
var hunger = 10
abstract fun makeNoise()
abstract fun eat()
open fun roam() {
println("animal is roaming")
}
fun sleep() {
println("animal is sleeping")
}
}
// 犬科
abstract class Canine: Animal() {
override fun roam() {
println("the canine is roaming)
}
}
// 實體類
// 需要對抽象類中的屬性和方法進(jìn)行實現(xiàn)
class Wolf: Canine() {
override val image = "wolf.jpg"
override val food = "meat"
override fun makeNoise() {
println("Hooowwwl")
}
override fun eat() {
println("the wolf is eating $food")
}
}
接口
kotlin和其它語言一樣,只能繼承一個類,但是可以實現(xiàn)多個接口。
- 一般寫法
使用 interface 關(guān)鍵詞,可以給出實現(xiàn),也可以不給出實現(xiàn)
// 不給出實現(xiàn), 則實體類必須自己提供實現(xiàn)
interface IFlyable {
fun fly()
}
// 給出實現(xiàn)
// 實體類可以選擇 override 也可以直接使用接口提供的實現(xiàn)
interface IFlyable {
fun fly() {
println("I can fly")
}
}
- Getter & setter
接口中還可以定義屬性,屬性能通過 get() 返回一個值,注意,不能直接進(jìn)行賦值初始化,因為接口沒有構(gòu)造器
// 錯誤寫法
interface IFlyable {
fun fly()
// error: Property initializers are not allowed in interfaces
val velocity: Int = 20
}
// 正確寫法
interface IFlyable {
fun fly()
// 注意這里要用val 不能使用var
val velocity: Int
get() = 20
}
setter 中不能使用 field, 因為接口中不存在向后引用字段
// 錯誤寫法
interface IFlyable {
fun fly()
// error: Property in an interface cannot have a backing field
var velocity: Int
get() = 20
set(value) {
if value > 0 {
field = value
}
}
}
// 正確寫法
interface IFlyable {
fun fly()
// 這里要使用var 因為val是只讀的 不存在setter
var velocity: Int
get() = 20
set(value) {
if value > 0 {
// 不使用 field 的其它操作 都可以
print("your value is greater than 0")
}
}
}
is & as & when
-
is用來判斷是否是某個類型,!is這個則相反 (第一次看到這種寫法)abstract class Animal { abstract val food: String fun eat() { println("animal is eating $food") } } class Dog: Animal() { override val food = "meat" fun bark() { println("a dog is barking") } } var a = Dog() if (a is Dog) { a.bark() } -
as: 用于進(jìn)行類型轉(zhuǎn)換,is會執(zhí)行智能轉(zhuǎn)換,但是有時候智能轉(zhuǎn)換會失敗,需要使用as進(jìn)行顯式的轉(zhuǎn)換interface IRunable { fun run() } abstract class Animal: IRunable { abstract val food: String fun eat() { println("animal is eating $food") } override fun run() { println("some animal can run") } } class Dog: Animal() { override val food = "meat" fun bark() { println("a dog is barking") } } class Ground { // 使用var 聲明 表示something可能會發(fā)生變化 var something: IRunable = Dog() fun showInfo() { // 看著沒什么問題 但是編輯器會報錯 // Smart cast to 'Dog' is impossible because 'something' is a mutable property that // could hae been changed by this time if (something is Dog) { something.bark() } } } // 解決辦法, 使用as 顯式的轉(zhuǎn)換 class Ground { // 使用var 聲明 表示something可能會發(fā)生變化 var something: IRunable = Dog() fun showInfo() { if (something is Dog) { (something as Dog).bark() // 進(jìn)行顯式轉(zhuǎn)換 } } } -
when: 這個就是其它語言中的switch...case// 用法1 聲明變量 var temperature = 30 var isCool: Boolean = when { temperature > 28 -> false else -> true } // 用法2 和 is 搭配 when (animal) { is Dog -> { // ... } is Cat -> { // ... } }
大致內(nèi)容:
類的定義
初始化塊
getter 和 setter (
field關(guān)鍵詞)-
類的繼承
- 注意修飾符的使用
open | final - 抽象類
-
var & val修飾屬性的差異,override 時需要注意, 還有 init block 的使用
- 注意修飾符的使用
-
接口的使用
- 可以提供默認(rèn)實現(xiàn) 也可以是抽象的
- 可以使用getter 和 setter, 但是setter 中不能使用
field
-
輔助邏輯關(guān)鍵詞
is & !isaswhen