kotlin入門潛修之類和對象篇—權(quán)限修飾符

本文收錄于 kotlin入門潛修專題系列,歡迎學(xué)習(xí)交流。

創(chuàng)作不易,如有轉(zhuǎn)載,還請備注。

訪問權(quán)限修飾符

訪問權(quán)限修飾符也可叫做可見性修飾符(Visibility Modifiers),了解java語言的應(yīng)該很清楚,這里先介紹下java中的四種權(quán)限訪問修飾符。

有朋友會說java不就三種訪問修飾符嗎?private、protected、public,還有什么訪問修飾符?

是的,通常我們常用的也就這三個,事實上也夠用了。其實java中還有一個默認(rèn)的default的權(quán)限控制,但是并沒有明確的關(guān)鍵字,當(dāng)定義字段的時候不寫private、protected、public就表示該字段是default。java中的權(quán)限修飾符可見性總結(jié)如下:

public protected default private
同一類中的成員
同一包中的成員
不同包中的子類
不同包中的非子類

接下來看下kotlin中的權(quán)限訪問修飾符

kotlin中也有四種權(quán)限訪問修飾符:private、protected、internal、public。kotlin中如果不顯示指定權(quán)限訪問修飾符,則默認(rèn)是public的,這個和java不太一樣。

kotlin中權(quán)限訪問修飾符可以修飾類、單例對象、接口、構(gòu)造方法、方法、屬性以及屬性的set方法。這里我們先一步步看下kotlin中的不同訪問權(quán)限場景,然后再給出一個權(quán)限訪問修飾符的總結(jié)列表。

top-level級別的權(quán)限訪問修飾符

kotlin中,類、方法、屬性、單例對象以及接口都可以被定義為top-level級別的,所謂top-level實際上前面已經(jīng)講到過,即脫離了類的控制,不在類中定義。如下所示:

package com.test
//下面的屬性、方法、class都直接定義在了com.test包下的Person.kt文件中,都屬于top-level級別的成員
val name = "zhangsan"http://沒有修飾符,則默認(rèn)是public,任何地方都可以使用
private val age = 20//private修飾,只能當(dāng)前文件中使用,即只能在Person.kt中使用
internal val state = "china"http://internal修飾,在同一個module中可以訪問
public var phone: Int = 5//其實這里public是多余的,默認(rèn)都是public的
    private set//注意這里使用private修飾了phone的set方法,表示只能在當(dāng)前文件中修改phone的值,外部無法修改。

protected val sex = "男"http://!!!編譯錯誤,top-level級別的成員無法使用protected修飾

internal fun getAddress(): String {//使用訪問權(quán)限修飾符修飾的方法的可見性同屬性一樣,這里也是同一個module可見
    return "hang zhou"
}

private fun printAge() {//只能在當(dāng)前文件中可見
    println(age)
}

class Person {//默認(rèn)是public
}

上面代碼中,已經(jīng)對各個場景做了詳細(xì)注釋。再總結(jié)一下:

  1. 如果沒有顯示指定訪問權(quán)限修飾符,則默認(rèn)是public,即隨處可見。
  2. 如果使用private修飾,則只能在當(dāng)前文件中使用。
  3. 如果使用internal修飾,則在同一個module中都是可見的。
  4. protected修飾符是不允許修飾top-level成員的。
    還需要注意一點,想要使用top-level成員,必須要import。如下所示:
//在另一個文件中使用上面Person.kt中的top-leve屬性name,則需要import
import com.test.name
class Test {
    fun test() {
        println(name)//import后即可使用
    }
}

最后,關(guān)于internal修飾符,總是說能在同一個module中訪問,那么什么是同一個module?kotlin中是這樣定義的:

  1. 一個intellij IDEA module。即使用idea ide 新建文件的時候,選擇的是module類型。
  2. 一個maven工程。這個用過maven的都應(yīng)該能理解。
  3. 一個gradle SourceSet。gradle和maven類似,后面會有文章來闡述kotlin和gradle。
  4. ant中, 使用kotlinc(針對jvm的kotlin編譯器)命令編譯的文件集合。
    一般情況下,第一種是我們自己建立的,后三種都是結(jié)合構(gòu)建工具進(jìn)行構(gòu)建的,后面文章會有所闡述,這里姑且了解下。

類和接口中的修飾符

照例,我們來先看一段代碼示例

//ParentClass,位于com.test包下
package com.test
open class ParentClass {
    private val a = 1
    protected open val b = 2
    internal val c = 3
    val d = 4
    protected class Nested {
        public val e = 5
    }
}

//ParentClass的子類SubClass
package com.test
class SubClass : ParentClass() {
    fun test() {
        Nested()//正確,子類能訪問protected
        super.a//編譯錯誤,private只能在同一個類中訪問
        super.b//正確,子類能訪問父類的protected成員
        super.c//正確,子類能訪問父類internal的成員
        super.d//正確,子類能訪問父類的public成員
    }
}

//同一個包下的成員
package com.test
class Test {
    fun test(){
        val p = ParentClass()
        p.c//正確,同一個包下的其他成員可以訪問另一個成員的internal成員
        p.d//正確,同一個包下的其他成員可以訪問另一個成員的public成員
        p.b//錯誤,同一個包下的其他成員無法訪問另一個成員的protected成員
        p.a//錯誤,同一個包下的其他成員無法訪問另一個成員的private成員
    }
}

上面例子已經(jīng)標(biāo)注了類和接口的訪問權(quán)限情況,但是相信很多朋友容易看出神,這里我們再總結(jié)下。

  1. private修飾,意味著只有在class內(nèi)部可見。
  2. protected修飾,在class內(nèi)部可見,子類中也可見。
  3. internal修飾,同一個module中可見。
  4. public修飾, 任何地方都可見。

另外需要注意的是:

  1. 外部類無法訪問內(nèi)部的類中的private和protected成員。如下所示:
open class ParentClass {
    fun test() {
        val nested = Nested()
        nested.e//正確,可以訪問內(nèi)部的類中的public修飾的成員
        nested.f//錯誤,無法訪問內(nèi)部的類中的protected修飾的成員
        nested.d//錯誤,無法訪問內(nèi)部的類中的private修飾的成員
    }
    protected class Nested {
        protected var f = 1;
        private var d = 2;
        val e = 5
        fun test() {
            val p = ParentClass()
            println()
        }
    }
  1. 在override一個屬性的時候,如果不改變其訪問權(quán)限修飾符,則默認(rèn)和父類一致。
  2. override只能擴充父類的訪問權(quán)限修飾符范圍,不能縮小。如父類使用了protected修飾,子類在override的時候可以修改為public,但不能修改為private。

構(gòu)造方法

構(gòu)造方法默認(rèn)的修飾符都是public的,可以顯示指定修飾符,如下所示:


class MyClass private constructor() {//private修飾的constructor,意味著只能在SubClass內(nèi)部生成對象,無法在外部生成對象。
    fun getInstance(): MyClass {//MyClass內(nèi)部可以使用,有沒有種java單例的感覺?
        return MyClass()
    }
}
//外部無法使用
class Test {
    val myClass = MyClass()//錯誤,MyClass構(gòu)造方法是私有的,無法再外部使用,也無法繼承
}

注意,private修飾構(gòu)造方法和修飾類是兩個概念,再看下下面的代碼

private open class MyClass constructor() {//這種方式表示MyClass這個類是私有的,對外界是不可見的,即外界無法使用,也無法繼承
}

總結(jié)

能看到這里的朋友應(yīng)該都是很厲害的了,因為我自己寫的時候都已經(jīng)很痛苦了,各種權(quán)限修飾,各種例子展示。在具體使用中如果時時記著這些場景確實很難受。當(dāng)然萬事萬物都有個熟能生巧的過程,寫多了自然而然就知道了,所以在徹底理解清楚之前,可以把本篇文章作為一個詞典,什么時候忘記了什么時候過來看一眼即可。

下面給出一份總結(jié):

  1. top-level級別的成員
public protected internal private
同一類中的成員 無法使用
同一module中的成員 無法使用
不同module中的成員 無法使用
  1. 類或接口的成員
public internal protected private
同一類中的成員
子類中的成員
同一module中的成員
不同module中的成員
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前言 人生苦多,快來 Kotlin ,快速學(xué)習(xí)Kotlin! 什么是Kotlin? Kotlin 是種靜態(tài)類型編程...
    任半生囂狂閱讀 26,692評論 9 118
  • Kotlin的類和接口與Java的類和接口是有一定的區(qū)別的。Kotlin的接口是可以包含屬性聲明。Kotlin默認(rèn)...
    程自舟閱讀 10,520評論 0 11
  • 本文收錄于 kotlin入門潛修專題系列,歡迎學(xué)習(xí)交流。 創(chuàng)作不易,如有轉(zhuǎn)載,還請備注。 屬性的定義 我們都知道在...
    寒瀟2018閱讀 854評論 0 2
  • 20180725 姓名:侯云生 公司:華利保模具(寧波)有限公司 謙虛一組學(xué)員 利他二組義志工 【六項精進(jìn)打卡第1...
    文止山閱讀 214評論 0 0
  • 冬天,世界變成了一塊冰 踩著烏云的倒影 聽見腳下的大地 吱呀作響,頭頂?shù)奶炜?碎裂出萬朵雪花 在你的眼角飛揚 走在...
    鱘余閱讀 176評論 0 1

友情鏈接更多精彩內(nèi)容