1. 程式人生 > >Kotlin 類和繼承

Kotlin 類和繼承

類宣告

Kotlin使用class關鍵字宣告類:

class Foo {
}

宣告分為宣告頭和宣告體。其中宣告體是可選的,如下:

class Bar

建構函式

Kotlin建構函式分為主建構函式(primary constructor)和輔助建構函式(secondary constructor)。

主建構函式

主建構函式在類頭中,緊跟類名之後。如果不修改主建構函式的可見性也不為主建構函式添加註解,那麼constructor關鍵字是可選的。主建構函式不包含任何程式碼,但是主建構函式將會執行init關鍵字標記的程式碼塊。並且主建構函式的形參可以在init程式碼塊中訪問,並用於初始化類成員變數:

class Person(name: String) {
    init {
        this.name = name.toUpperCase()
    }
}

// 帶有可見性宣告或者是註解的主建構函式,contructor 關鍵字不能省略!!!
class Person private @Inject constructor(name: String) {
    // ...
}

我們甚至可以直接在主建構函式中宣告並初始化類屬性(能做的也僅止於此了~)。如下:

class Person(val firstName: String, val lastName: String, var age: Int) {
    // ...
}

輔助建構函式

類可以在類體中定義若干個輔助建構函式。輔助建構函式使用constructor 標記:

class Person(name: String) {
    constructor(parent: Person, name: String): this(name) {
        parent.children.add(this)
    }
}

如上,如果函式定義了一個主建構函式,那麼所有的輔助建構函式必須使用this呼叫主建構函式(直接呼叫或者通過呼叫其他輔助建構函式間接呼叫)。

如果沒有主建構函式或者輔助建構函式被定義,編譯器將自動生成無參主建構函式。主建構函式的預設訪問許可權為public

,如果需要修改可見性,可以定義一個空的無參建構函式同時指定可見性。

class DontCreateMe private constructor() {
}

如果執行在JVM上,類的主建構函式的所有引數都有預設值,編譯器將會自動生成無參建構函式,並使用預設引數值初始化。這有益於Kotlin類用於某些Java庫中。

建立類的例項

Kotlin中沒有new 關鍵字。所以相對於Java,省略掉new就可以了~ 如下:

val apple = Apple()
val person = Person("Tom")

類繼承

類似於Java中的Object類,Any 類是Kotlin中所有其它類的預設基類。Any類不是Java中的Object類Any 類只包含equals()hashCode()toString()方法。

描述繼承關係的方法與C++類似使用冒號,而不是使用Java中的“extend”或“implement”,Kotlin中沒有這倆關鍵字。

Koltin中的類預設是final不可以被繼承,對於需要被繼承的類,必須顯式地標記為open

  • 如果派生類有主建構函式,那麼必須在派生類主建構函式呼叫基類的建構函式完成基類初始化。
  • 如果派生類沒有主建構函式,那麼就必須在派生類的每一個建構函式中都呼叫super()函式完成基類的初始化。
// 需要被繼承的基類,必須用open標記!
open class Base(p: Int)

// 派生類有主建構函式,必須在主建構函式之後呼叫基類的建構函式
class Derived_1(p: Int): Base(p)

// 派生類沒有主建構函式,必須在所有的輔助建構函式中呼叫基類的建構函式
class Derived_2 {
    constructor(p: Int): super(p)

    constructor(): super(0)
}

方法覆蓋(override)

不同於Java中可選的註解,Kotlin中方法覆蓋需要強制使用關鍵字openoverride

基類中被覆蓋的方法必須使用open關鍵字標記,而派生類中覆蓋基類方法的新方法必須使用override關鍵字標記:

open class Base {
    open fun f1() {}
    fun f2() {}
}

class Derived(): Base() {
    override fun f1() {}
}

如上,基類中只有f1()是可以被覆蓋的,並且在派生類中覆蓋f1()必須使用override關鍵字。

方法的標記總是不能和類的標記衝突,也即含有open函式的類必須也是open的!

如果派生類是open的,含有override標記的方法會預設成為open,這與之前的預設規則不同。如果不想讓派生類中覆蓋的方法進一步被覆蓋,那就需要新增final關鍵字。如下:

open AnotherDerived(): Base() {
    final override fun f1() {}
}

屬性覆蓋

屬性覆蓋和方法覆蓋差不多,同樣的openoverride使用規則!

可以通過指定新的 get 方法,或提供初始值來覆蓋屬性。

可以使用var屬性覆蓋val屬性,這相當於在派生類中新增一個 set 方法;但是不能使用val 屬性覆蓋var屬性,這相當於繼承了基類的 set 方法卻無法再派生類中使用。

interface Foo {
    val count: Int
    val x: Int
}

class Bar1(override val count: Int) : Foo

class Bar2 : Foo {
    override var count: Int = 0
    override val x: Int get {...}
}

呼叫基類的方法

一句話!使用 super ~

如果是內部類需要訪問外部類的基類。假設外部類名為 Outer,那麼呼叫方法為[email protected]。如下:

class Bar : Foo() {
    override fun f() { /* ... */ }
    override val x: String get() = "..."

    inner class Baz {
        fun g() {
            super@Bar.f() // Calls Foo's implementation of f()
            println(super@Bar.x) // Uses Foo's implementation of x's getter
        }
    }
}

覆蓋規則

  1. 如果繼承來的多個名稱(來自介面或者基類)衝突,派生類必須覆蓋這個方法;
  2. 在派生類中訪問基類(或者介面)名稱的實現,如果存在多個實現那麼必須使用super<BaseType>語法指定基類。
open class A {
    open fun f() { print("A") }
    fun a() { print("a") }
}

interface B {
    fun f() { print("B") } // interface members are 'open' by default
    fun b() { print("b") }
}

class C() : A(), B {
    // The compiler requires f() to be overridden:
    override fun f() {
        super<A>.f() // call to A.f()
        super<B>.f() // call to B.f()
    }
}

抽象類

包含抽象方法的類必須是抽象類。

抽象類和抽象方法都是用abstract關鍵字標記。

和介面一樣,抽象類和抽象介面預設為open

可以用一個抽象方法覆蓋非抽象方法。

相關推薦

Kotlin 繼承

類宣告 Kotlin使用class關鍵字宣告類: class Foo { } 宣告分為宣告頭和宣告體。其中宣告體是可選的,如下: class Bar 建構函式 Kotlin建構函式分為主建構函式(primary constructor)和輔助

Android知識體系梳理筆記五:Kotlin學習筆記一:繼承以及Anko(全)的基本使用

前言 對於kotlin,我是邊寫專案邊學的方式來學習的,這些都是在做專案的時候遇到的問題及擴充套件學習的時候記錄的,雖然有些內容不會涉及,但是我認為這種邊寫程式碼邊學習的方式特別有助於記憶,畢竟紙上得來終覺淺! 類和繼承 Kotlin較Java在繼承和實現

Kotlin-2.1-繼承

Kotlin-2.1-Classes and Inheritance 標籤:Kotlin 本節介紹了Kotlin中類和繼承的內容。類中包含首要構造器和次要構造器,還有類成員:屬性(Java中成員變數)和函式(Java中方法)。繼承主要講解的是如何過載

Kotlin程式設計之父繼承

Kotlin程式設計相關知識點介紹: 1. 預設繼承Any超類: 在Kotlin程式設計中,Any類是超類. public open class Any { public o

《C#圖解教程》讀書筆記之四:繼承

intern html pan 類中訪問 ted obj 小寫 his new 本篇已收錄至《C#圖解教程》讀書筆記目錄貼,點擊訪問該目錄可獲取更多內容。 一、萬物之宗:Object   (1)除了特殊的Object類,其他所有類都是派生類,即使他們沒有顯示基類定義。   

ts-繼承

world end spa nbsp moved move clas let new class Greeter { greeting: string; constructor(message: string) { this.greetin

Kotlin繼承

kotlin類Kotlin使用class關鍵字聲明類,類聲明由類名、類頭(指定其類型參數、主 構造函數等)和由大括號包圍的類體組成。類頭和類體都是可選的,如果一個類沒有類體大括號可省略class NoBody類的構造函數一類可以有一個主構造函數和一個或多個次構造函數。主構造函數是類頭的一部分:它跟在類名(和可

C#圖解 繼承

類的方法 png gpo 派生類 引用調用 有一個 圖解 匹配 關於 ---恢復內容開始--- 一:類繼承: 派生類成員組成如下: 1:自己聲明的成員 基類的成員 2:派生類不能刪除他所繼承的任何成員 例如:展示了名為OtherClass的類的聲明,他繼承的名

從零開始學Kotlin-對象(5)

int 文件中 cls 間接 main dcl this 調用 定義類 從零開始學Kotlin基礎篇系列文章 定義一個類 定義一個類,使用關鍵字class聲明,後面跟類名(不使用new) class demo5 {//定義一個類,使用關鍵字class聲明,後面跟類名

(轉載)【笨木頭Lua專欄】基礎補充20:面向對象——繼承

笑話 ava span 生成 code BE 手機 情況 忽略 終於來了,在Lua中的面向對象編程,相信目前學習Lua的大部分人都是為了開發手機網遊吧。而且基本都是奔著腳本語言的熱更新特性去的,所以全腳本開發變得十分流行。 對於普及不太廣的Lua(相對於C++、Java等主

繼承

局部變量 不能 訪問權限 abs bstr 允許 fin 構造 個數 任何類都是Object類(java.lang包中的類)的子孫類。 子類和父類在同一個包中:不繼承private成員變量和private方法。 子類和父類不在同一個包中:不繼承private和友好訪問權限

How Javascript works (Javascript工作原理) (十五) 繼承及 Babel TypeScript 代碼轉換探秘

屬性集 重寫 details 函數調用 有趣的 feature 性能優化 mage 轉化 個人總結:讀完這篇文章需要15分鐘,文章主要講解了Babel和TypeScript的工作原理,(例如對es6 類的轉換,是將原始es6代碼轉換為es5代碼,這些代碼中包含著類似於 _c

繼承

代碼 ret 包含 protect 轉換成 intern mas obj int 所有的類都派生自Object; 派生類引用可以轉換成基類; 屏蔽基類成員使用關鍵字new則可以屏蔽基類成員; 虛方法和覆寫方法 基類的方法被標記為virtual 在派生類中有匹配的ove

Kotlin物件

“用Kotlin開發android更簡潔( ̄_, ̄ )” 官方文件 翻譯文件 類和繼承 類的申明 和java一樣可以用這種方式 class Empty { } //kotlin提供了一種更為簡潔的方式建立無實體型別 class Empt

探究Java中的繼承--------Java的系列學習之路(15)

前言—— 今天是軍訓的第5天,昨天打了一天的軍體拳(哈哈哈,好好看本篇博文,不然博主一套軍體拳下去你可能會殘疾  :) 明天是最後一天了,今晚繼續做自己手頭上的事,避免碌碌無為。今天講解的內容——類和繼承,也是跟上一篇一樣,基礎且重要。 第5天沒把這篇文章寫完,今天第六

kotlin 繼承

與Java不同,kotlin 使用冒號,而Java 中使用extends, 注意冒號後面需要呼叫夫類的構造器。屬於單繼承,使用open 關鍵字允許繼承class package loaderman.demo open class Person (name:String){ prot

ES6繼承

首先看程式碼 class Person { constructor(name){ console.log(`建構函式執行了,${name}`) } } let p1=

Python3 繼承

1 import random as r 2 3 class Fish: 4 def __init__(self): 5 self.x = r.randint(0,10) 6 self.y = r.randint(0,10) 7 8 d

【原型原型鏈】繼承

一、定義“類” ——建構函式 我們知道,JavaScript中沒有類的概念,我們只是通過函式來模仿類的行為,我們將它稱之為建構函式 建構函式分兩類,原生建構函式和自定義建構函式。原生建構函式像Array、Object,是執行環境自動提供的;

python中的繼承學習筆記

與C++和JAVA一樣,python也是一種面向物件的語言,但具體使用和C++有一些不同之處。下面按照封裝、繼承、多型的順序對python面向物件程式設計進行一個總結。封裝class testclass1: def __init__(self): pr