本人也是在初學(xué)Kotlin,如有錯誤,請幫忙指出,持續(xù)更新
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-類和對象(下)-基礎(chǔ)語法(五)
建議先看看前面的文章
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-基礎(chǔ)語法(一)
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-基本類型-基礎(chǔ)語法(二)
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-包-控制流-返回與跳轉(zhuǎn)-基礎(chǔ)語法(三)
Android:Kotlin詳細(xì)入門學(xué)習(xí)指南-類和對象-基礎(chǔ)語法(四)
這篇文章分享的內(nèi)容比較多,建議先關(guān)注收藏,再查看,以免迷路
抽象類
一個類或一些成員可能被聲明成 abstract 。一個抽象方法在它的類中沒有實現(xiàn)方 法。記住我們不用給一個抽象類或函數(shù)添加 open 注解,它默認(rèn)是帶著的。
abstract class Derived : Base() {
override abstract fun f()
}
伴隨對象
在 kotlin 中不像 java 或者 C# 它沒有靜態(tài)方法。在大多數(shù)情形下,我們建議只用包 級別的函數(shù)。
在kotlin中如果我們想直接調(diào)用某個方法可以添加@JvmStatic注解也可以使用companion伴生對象,如果想直接使用一個屬性,使用@JvmField
class StringUtils{
companion object {
fun isEmpty(str:String):Boolean{
return "".equals(str)
}
}
}
屬性和字段
屬性聲明
在 Kotlin 中類可以有屬性,我們可以使用 var 關(guān)鍵字聲明可變屬性,或者用 val 關(guān) 鍵字聲明只讀屬性。
可以像使用 java 中的字段那樣,通過名字直接使用一個屬性:
val result = Address() // 在 kotlin 中沒有 new 關(guān)鍵字
Getters 和 Setters
語法中的初始化語句,getter 和 setter 都是可選的。如果屬性類型可以從初始化語 句或者類的成員函數(shù)中推斷出來,那么他的類型也是忽略的。
只讀屬性的聲明語法和可變屬性的聲明語法相比有兩點不同: 它以 val 而不是 var 開頭,不允許 setter 函數(shù)。
編譯時常量
那些在編譯時就能知道具體值的屬性可以使用 const 修飾符標(biāo)記為 編譯時常量
const val SUBSYSTEM_DEPRECATED: String = "This subsystem is depr ecated
延遲初始化屬性
這個修飾符只能夠被用在類的 var 類型的可變屬性定義中,不能用在構(gòu)造方法中. 并且屬性不能有自定義的 getter 和 setter訪問器.這個屬性的類型必須是非空的,同 樣也不能為一個基本類型屬性加上 lateinit 修飾符。
接口
Kotlin 的接口很像 java 8。它們都可以包含抽象方法,以及方法的實現(xiàn)。和抽象類 不同的是,接口不能保存狀態(tài)??梢杂袑傩缘仨毷浅橄蟮?,或者提供訪問器的實現(xiàn)。
接口用關(guān)鍵字 interface 來定義:
interface MyInterface {
fun bar()
fun foo() {
//函數(shù)體是可選的
}
}
實現(xiàn)接口
一個類或?qū)ο罂梢詫崿F(xiàn)一個或多個接口
class Child : MyInterface {
fun bar () { //函數(shù)體
}
}
接口中的屬性
可以在接口中申明屬性。接口中的屬性要么是抽象的,要么提供訪問器的實現(xiàn)。接 口屬性不可以有后備字段。而且訪問器不可以引用它們。
可見性修飾詞
類,對象,接口,構(gòu)造函數(shù),屬性以及它們的 setter 方法都可以有可見性修飾詞。( getter與對應(yīng)的屬性擁有相同的可見性)。在 Kotlin 中有四種修飾 詞: private , protected , internal ,以及 public 。默認(rèn)的修飾符是 public 。
包
函數(shù),屬性和類,對象和接口可以在 "top-level" 聲明,即可以直接屬于包:
// 文件名: example.kt
package foo
fun baz() {}
class bar {}
- 如果沒有指明任何可見性修飾詞,默認(rèn)使用 public ,這意味著你的聲明在 任何地方都可見;
- 如果你聲明為 private ,則只在包含聲明的文件中可見;
- 如果用 internal 聲明,則在同一模塊中的任何地方可見;
- protected 在 "top-level" 中不可以使用
// 文件名: example.kt
package foo
private fun foo() {} // 在example.kt可見
public var bar: Int = 5 // 屬性在認(rèn)可地方都可見
private set // setter僅在example.kt中可見
internal val baz = 6 // 在同一module中可見
構(gòu)造函數(shù)
通過下面的語法來指定主構(gòu)造函數(shù)(必須顯示的使用 constructor 關(guān)鍵字)的可見性:
class C private constructor(a: Int) { ... }
這里構(gòu)造函數(shù)是 private 。所有的構(gòu)造函數(shù)默認(rèn)是 public ,實際上只要類是可見 的它們就是可見的 (注意 internal 類型的類中的 public 屬性只能在同一個模塊 內(nèi)才可以訪問)
函數(shù)擴(kuò)展
為了聲明一個函數(shù)擴(kuò)展,我們需要在函數(shù)前加一個接收者類型作為前綴。下面我們 會為 MutableList<Int> 添加一個 swap 函數(shù):
fun MutableList<Int>.swap(x: Int, y: Int) {
val temp = this[x] // this 對應(yīng) list
this[x] = this[y]
this[y] = tmp
}
在擴(kuò)展函數(shù)中的 this 關(guān)鍵字對應(yīng)接收者對象?,F(xiàn)在我們可以在任何 MutableList<Int> 實例中使用這個函數(shù)了:
val l = mutableListOf(1, 2, 3)
l.swap(0, 2)// 在 `swap()` 函數(shù)中 `this` 持有的值是 `l`
屬性擴(kuò)展
和函數(shù)類似, Kotlin 也支持屬性擴(kuò)展:
val <T> List<T>.lastIndex: Int
get() = size-1
注意,由于擴(kuò)展并不會真正給類添加了成員屬性,因此也沒有辦法讓擴(kuò)展屬性擁有 一個備份字段.這也是為什么初始化函數(shù)不允許有擴(kuò)展屬性。擴(kuò)展屬性只能夠通過明 確提供 getter 和 setter方法來進(jìn)行定義.
伴隨對象擴(kuò)展
如果一個對象定義了伴隨對象,你也可以給伴隨對象添加擴(kuò)展函數(shù)或擴(kuò)展屬性:
class MyClass {
companion object {}
}
fun MyClass.Companion.foo(){
}
MyClass.foo()
數(shù)據(jù)類
和java的bean類似
data class User(val name: String, val age: Int)
泛型
像 java 一樣,Kotlin 中的類可以擁有類型參數(shù):
class Box<T>(t: T){
var value = t
}
嵌套類
類可以嵌套在其他類中
class Outer {
private val bar: Int = 1
class Nested {
fun foo() = 2
}
}
val demo = Outer.Nested().foo() //==2
內(nèi)部類
類可以標(biāo)記為 inner 這樣就可以訪問外部類的成員。內(nèi)部類擁有外部類的一個對象 引用:
class Outer {
private val bar: Int = 1
inner class Inner {
fun foo() = bar
}
}
val demo = Outer().Inner().foo() //==1
匿名內(nèi)部類
匿名內(nèi)部類的實例是通過 對象表達(dá)式 創(chuàng)建的
window.addMouseListener(object: MouseAdapter() {
override fun mouseClicked(e: MouseEvent) {
// ...
}
override fun mouseEntered(e: MouseEvent) { // ...
}
})
對象聲明
單例模式是一種很有用的模式,Kotln 中聲明它很方便
object DataProviderManager {
fun registerDataProvider(provider: DataProvider) { // ...
}
val allDataProviders: Collection<DataProvider>
get() = // ...
}
DataProviderManager.registerDataProvider(...)
這叫做對象聲明,跟在 object 關(guān)鍵字后面是對象名。和變量聲明一樣,對象聲明并 不是表達(dá)式,而且不能作為右值用在賦值語句。
伴隨對象
在類聲明內(nèi)部可以用 companion 關(guān)鍵字標(biāo)記對象聲明:
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
val instance = MyClass.create()