Kotlin基礎(三)類、對象和接口

 

類、對象和接口

1、定義類的繼承結構

一)Kotlin中的接口

Kotlin的接口與Java8中類似,它們能夠包含抽象方法的定義以及非抽象方法的實現,但它們不能包含任何狀態。dom

 1 interface Clickable{
 2     fun click()
 3     fun showoff()=println("It's show time!")
 4 }
 5 
 6 interface Focusable{
 7     fun setFocus(b: Boolean)=
 8             println("I ${if (b) "got" else "lost"} focus.")
 9     fun showoff()= println("Kotlin")
10 }
11 
12 class Button: Clickable, Focusable{
13     //override用法同Java@Override但爲強制要求
14     override fun click() {
15         println("I was clicked!")
16     }
17     
18     //這裏若是沒有顯示地實現showoff,會獲得編譯錯誤
19     override fun showoff(){
20         //Java中的用法:Clickable.super.showoff();
21         /*super<Clickable>.showoff()
22         super<Focusable>.showoff()*/
23         println("Method of son.")
24     }
25 }

二)控制繼承的修飾符:open、final和abstract:默認爲final

 1 /**
 2 * Java中的類和方法默認是open的,而Kotlin中默認是final的。
 3 * 若是你想容許一個類建立一個子類,須要使用open修飾符來標識這個類
 4 * 方法與屬性也是如此。
 5 * */
 6 open class Button: Clickable{
 7     //這個函數是open的
 8     override fun click() {
 9         println("Clicking it")
10     }
11     //這個函數再也不是open的了
12     final override fun showoff()= println("Show off")
13     open fun animate(){}
14 }
15 
16 /**
17 * abstract類與Java中的相同,不能被實例化。
18 * 
19 * */
20 abstract class Animated{
21     //這個函數是抽象的,必須被子類實現,因此也是open的
22     abstract fun animated()
23     
24     //抽象類中的非抽象函數並非默認open的,但能夠標註爲open的
25     open fun stopAnimating()= println("Stop it!")
26 }

三)可見性修飾符:public,protected,internal和private,默認爲public

可見性修飾符幫助控制對代碼庫中聲明的訪問。Java中默承認見性爲-----包私有,在Kotlin只把包做爲在命名空間裏組織代碼的一種方式使用,並無將其用做可見性控制。ide

做爲替代Kotlin中提供了一種新的修飾符---internal,表示"只在模塊(一組一塊兒編譯的Kotlin文件)內部可見"。另一個區別就是Kotlin容許在頂層聲明中使用private可見性,函數

使這些聲明只會在聲明他們的文件中可見。post

 1 open internal class Button{
 2     private fun click()= println("Hey!")
 3     protected fun showoff()= println("show it")
 4 }
 5 
 6 /*
 7 fun Button.fMethod(){ //錯誤:public成員暴露了其"internal"接收者類型B
 8     yell() //錯誤
 9     showoff() //錯誤
10 }
11 */
12 
13 internal fun Button.fMethod(){
14     /*showoff()  任然錯誤*/ 
15 }

另外一個與Java可見性不一樣的是:一個外部類不能看到其內部類或嵌套類中的private成員。this

四)內部類和嵌套類:默認爲嵌套類

只須要記住Kotlin中沒有顯示修飾符的嵌套類與Java中的static嵌套類是同樣的,若是要使其持有外部類的引用的話須要使用inner修飾符。spa

引用外部類實例語法:this@outercode

五)密封類:定義受限的類繼承結構

爲父類添加一個sealed修飾符,對可能建立的子類作出嚴格限制,全部的直接子類必須嵌套在父類中。對象

請思考這樣作的好處。blog

 

2、聲明一個帶默認構造方法或屬性的類

一)初始化類:主構造方法和初始化語句塊

 1 class User0(val name: String="tang"/*可提供默認值*/) /*簡便寫法,其中val關鍵字意味着
 2 相應的屬性會用構造方法的參數來初始化*/
 3 
 4 open class User constructor(name: String)/*帶參數的主構造方法,constructor
 5     用來聲明一個主構造方法和一個從構造方法*/{
 6     val name:String
 7     
 8     init { //初始化語句塊,由於主構造方法的語法限制,全部有了初始化語句
 9         //一個類中能夠聲明多個初始化語句
10         this.name=name
11     }
12 }
13 
14 //若是一個類具備父類,主構造方法一樣須要初始化父類。
15 // 即便父類構造函數沒有任何參數,也要顯示地調用構造函數。
16 class TwitterUser(name: String) : User(name){}
17 
18 //若是要確保類不被實例化,能夠把構造函數標記爲private
19 class Person private constructor(val name: String)

二)構造方法:用不一樣的方法來初始化父類

 1 //沒有主構造函數
 2 open class View{
 3     constructor(ctx: String)
 4     constructor(ctx: String, attr: String)
 5 }
 6 
 7 class MyButton : View{
 8     constructor(ctx: String) :this(ctx,"s")
 9     
10     constructor(ctx: String,attr: String) : super(ctx,attr){
11         /*some code*/
12     }
13 }

三)實如今接口中聲明的屬性

 1 /*接口能夠包含抽象屬性聲明*/
 2 interface User{
 3     val nickname: String
 4     /*接口還可包含具備getter和setter的屬性,只要他們沒有引用一個支持字段*/
 5     val age: Int
 6         get() = Random().nextInt(100)
 7 }
 8 
 9 /*在實現了接口的類中必須override該屬性*/
10 class QQUser (override val nickname: String) : User
11 
12 class BaiduUser(val email: String) : User{
13     override val nickname: String
14         get() = "Baidu $email"
15 }

四)經過getter或setter訪問支持字段

 1 class User(val name: String){
 2     var address: String="unspecified"
 3         //在set函數體中,使用了標識符field來訪問支持字段的值。
 4         //在get函數中只能讀取它,在set函數中能夠修改它。
 5         set(value: String) {
 6             println("""
 7                 Address was changed for $name: "$field" -> "$value".""".trimIndent())
 8         }
 9 }
10 
11 fun main(args: Array<String>) {
12     val user=User("Tom")
13     user.address="Back Street 221"
14     user.address="Beijing hu tong 222"
15     /*Address was changed for Tom: "unspecified" -> "Back Street 221".
16       Address was changed for Tom: "unspecified" -> "Beijing hu tong 222".*/
17     
18 }

五)修改訪問其可見性

1 class LengthCounter{
2     var counter: Int=0
3         private set //聲明爲private,不能再類外部修改這個屬性
4     
5     fun addWord(word: String){
6         counter+=word.length
7     }
8 }

3、編譯器生成的方法:數據類和類委託

   一)通用的對象方法

1.toString()繼承

2.equals():在Kotlin中"=="至關於Java中的equals,"==="至關於Java中的"=="(比較引用)   

3.hashCode()方法一般與equals方法一塊兒被重寫(若是兩個對象相等,它們一般必須有相同的hash值)。

 1 class Client(val name: String,val postalCode: Int){
 2     override fun equals(other: Any?): Boolean {
 3         if (other==null || other !is Client) return false
 4         return name==other.name && postalCode==other.postalCode
 5     }
 6 
 7     override fun toString(): String {
 8         return "Client($name,$postalCode)"
 9     }
10 
11     override fun hashCode(): Int {
12         return name.hashCode()*12+postalCode
13     }
14 }

二)數據類:自動生成通用方法實現

若是爲類添加data修飾符,上述通用方法將會被自動生成好。其中

1.equals方法:檢測因此主構造函數屬性的值是否相等。

2.hashCode方法:返回一個根據全部主構造函數中屬性值生成的哈希值。

注意:沒有在主構造函數中聲明的屬性將不會加入到相等性檢測和哈希值計算中去。

data class User(val name: String,val age:Int,val gender: String)

三)類委託:使用"by"關鍵字

class TangCollection<T>(
        val innerList: Collection<T> = ArrayList<T>()
) : Collection<T> by innerList {}

四)"object"關鍵字:將聲明一個類與建立一個實例結合起來

object關鍵字:定義一個類的同時建立一個實例

一)對象聲明:建立單例

/*
* 在定義的時候就被建立,而且爲一個單例
* */
object User {
    val name: String = "Tang"
    val age: Int = 8
}

二)伴生對象:工廠方法和靜態成員的地盤

class A {
    companion object {
        fun t(){
            println("Tang")
        }
    }
}

fun main(args: Array<String>) {
    A.t()
}

三)做爲普通對象使用的伴生對象

相關文章
相關標籤/搜索