本期做者:java
視頻:扔物線(朱凱)git
文章:Walker(張磊)github
你們好,我是扔物線朱凱。這是碼上開學 Kotlin 基礎部分的第二期:Kotlin 裏那些「不是那麼寫的」。話很少說,視頻伺候。編程
由於我一直沒有學會怎麼在掘金貼視頻,因此請點擊 這裏 去嗶哩嗶哩看,或者點擊 這裏 去 YouTube 看。數組
如下內容來自文章做者 Walker。安全
上一篇咱們講了 Kotlin 上手最基礎的三個點:變量、函數和類型。你們都據說過,Kotlin 徹底兼容 Java,這個意思是用 Java 寫出來的代碼和 Kotlin 能夠完美交互,而不是說你用 Java 的寫法去寫 Kotlin 就徹底沒問題,這個是不行的。這期內容咱們就講一下,Kotlin 裏那些「不 Java」的寫法。性能優化
上一篇中簡單介紹了 Kotlin 的構造器,這一節具體看看 Kotlin 的構造器和 Java 有什麼不同的地方:數據結構
Java架構
☕️
public class User {
int id;
String name;
👇 👇
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
複製代碼
Kotlinide
🏝️
class User {
val id: Int
val name: String
👇
constructor(id: Int, name: String) {
//👆 沒有 public
this.id = id
this.name = name
}
}
複製代碼
能夠發現有兩點不一樣:
constructor
表示。除了構造器,Java 裏經常配合一塊兒使用的 init 代碼塊,在 Kotlin 裏的寫法也有了一點點改變:你須要給它加一個 init
前綴。
Java
☕️
public class User {
👇
{
// 初始化代碼塊,先於下面的構造器執行
}
public User() {
}
}
複製代碼
Kotlin
🏝️
class User {
👇
init {
// 初始化代碼塊,先於下面的構造器執行
}
constructor() {
}
}
複製代碼
正如上面標註的那樣,Kotlin 的 init 代碼塊和 Java 同樣,都在實例化時執行,而且執行順序都在構造器以前。
上一篇提到,Java 的類若是不加 final 關鍵字,默認是能夠被繼承的,而 Kotlin 的類默認就是 final 的。在 Java 裏 final 還能夠用來修飾變量,接下來讓咱們看看 Kotlin 是如何實現相似功能的。
final
Kotlin 中的 val
和 Java 中的 final
相似,表示只讀變量,不能修改。這裏分別從成員變量、參數和局部變量來和 Java 作對比:
Java
☕️
👇
final int final1 = 1;
👇
void method(final String final2) {
👇
final String final3 = "The parameter is " + final2;
}
複製代碼
Kotlin
🏝️
👇
val fina1 = 1
// 👇 參數是沒有 val 的
fun method(final2: String) {
👇
val final3 = "The parameter is " + final2
}
複製代碼
能夠看到不一樣點主要有:
上一期說過,var
是 variable 的縮寫, val
是 value 的縮寫。
其實咱們寫 Java 代碼的時候,不多會有人用 final
,但 final
用來修飾變量實際上是頗有用的,但你們都不用;可你若是去看看國內國外的人寫的 Kotlin 代碼,你會發現不少人的代碼裏都會有一堆的 val
。爲何?由於 final
寫起來比 val
麻煩一點:我須要多寫一個單詞。雖然只麻煩這一點點,但就致使不少人不寫。
這就是一件頗有意思的事:從 final
到 val
,只是方便了一點點,但卻讓它的使用頻率有了巨大的改變。這種改變是會影響到代碼質量的:在該加限制的地方加上限制,就能夠減小代碼出錯的機率。
val
自定義 getter不過 val
和 final
仍是有一點區別的,雖然 val
修飾的變量不能二次賦值,但能夠經過自定義變量的 getter 函數,讓變量每次被訪問時,返回動態獲取的值:
🏝️
👇
val size: Int
get() { // 👈 每次獲取 size 值時都會執行 items.size
return items.size
}
複製代碼
不過這個屬於 val
的另一種用法,大部分狀況下 val
仍是對應於 Java 中的 final
使用的。
static
property / function剛纔說到你們都不喜歡寫 final
對吧?但有一種場景,你們是最喜歡用 final
的:常量。
☕️
public static final String CONST_STRING = "A String";
複製代碼
在 Java 裏面寫常量,咱們用的是 static
+ final
。而在 Kotlin 裏面,除了 final
的寫法不同,static
的寫法也不同,並且是更不同。確切地說:在 Kotlin
裏,靜態變量和靜態方法這兩個概念被去除了。
那若是想在 Kotlin 中像 Java 同樣經過類直接引用該怎麼辦呢?Kotlin 的答案是 companion object
:
🏝️
class Sample {
...
👇
companion object {
val anotherString = "Another String"
}
}
複製代碼
爲啥 Kotlin 越改越複雜了?不着急,咱們先看看 object
是個什麼東西。
object
Kotlin 裏的 object
——首字母小寫的,不是大寫,Java 裏的 Object
在 Kotlin 裏不用了。
Java 中的
Object
在 Kotlin 中變成了Any
,和Object
做用同樣:做爲全部類的基類。
而 object
不是類,像 class
同樣在 Kotlin 中屬於關鍵字:
🏝️
object Sample {
val name = "A name"
}
複製代碼
它的意思很直接:建立一個類,而且建立一個這個類的對象。這個就是 object
的意思:對象。
在代碼中若是要使用這個對象,直接經過它的類名就能夠訪問:
🏝️
Sample.name
複製代碼
這不就是單例麼,因此在 Kotlin 中建立單例不用像 Java 中那麼複雜,只須要把 class
換成 object
就能夠了。
單例類
咱們看一個單例的例子,分別用 Java 和 Kotlin 實現:
Java 中實現單例類(非線程安全):
☕️
public class A {
private static A sInstance;
public static A getInstance() {
if (sInstance == null) {
sInstance = new A();
}
return sInstance;
}
// 👇還有不少模板代碼
...
}
複製代碼
能夠看到 Java 中爲了實現單例類寫了大量的模版代碼,稍顯繁瑣。
Kotlin 中實現單例類:
🏝️
// 👇 class 替換成了 object
object A {
val number: Int = 1
fun method() {
println("A.method()")
}
}
複製代碼
和 Java 相比的不一樣點有:
class
換成了 object
。sInstance
。getInstance()
方法。相比 Java 的實現簡單多了。
這種經過
object
實現的單例是一個餓漢式的單例,而且實現了線程安全。
繼承類和實現接口
Kotlin 中不只類能夠繼承別的類,能夠實現接口,object
也能夠:
🏝️
open class A {
open fun method() {
...
}
}
interface B {
fun interfaceMethod()
}
👇 👇 👇
object C : A(), B {
override fun method() {
...
}
override fun interfaceMethod() {
...
}
}
複製代碼
爲何 object 能夠實現接口呢?簡單來說 object 實際上是把兩步合併成了一步,既有 class 關鍵字的功能,又實現了單例,這樣就容易理解了。
匿名類
另外,Kotlin 還能夠建立 Java 中的匿名類,只是寫法上有點不一樣:
Java:
☕️ 👇
ViewPager.SimpleOnPageChangeListener listener = new ViewPager.SimpleOnPageChangeListener() {
@Override // 👈
public void onPageSelected(int position) {
// override
}
};
複製代碼
Kotlin:
🏝️
val listener = object: ViewPager.SimpleOnPageChangeListener() {
override fun onPageSelected(position: Int) {
// override
}
}
複製代碼
和 Java 建立匿名類的方式很類似,只不過把 new
換成了 object:
:
new
用來建立一個匿名類的對象object:
也能夠用來建立匿名類的對象這裏的 new
和 object:
修飾的都是接口或者抽象類。
companion object
用 object
修飾的對象中的變量和函數都是靜態的,但有時候,咱們只想讓類中的一部分函數和變量是靜態的該怎麼作呢:
🏝️
class A {
👇
object B {
var c: Int = 0
}
}
複製代碼
如上,能夠在類中建立一個對象,把須要靜態的變量或函數放在內部對象 B 中,外部能夠經過以下的方式調用該靜態變量:
🏝️
A.B.c
👆
複製代碼
類中嵌套的對象能夠用 companion
修飾:
🏝️
class A {
👇
companion object B {
var c: Int = 0
}
}
複製代碼
companion
能夠理解爲伴隨、伴生,表示修飾的對象和外部類綁定。
但這裏有一個小限制:一個類中最多隻能夠有一個伴生對象,但能夠有多個嵌套對象。就像皇帝后宮佳麗三千,但皇后只有一個。
這樣的好處是調用的時候能夠省掉對象名:
🏝️
A.c // 👈 B 沒了
複製代碼
因此,當有 companion
修飾時,對象的名字也能夠省略掉:
🏝️
class A {
// 👇 B 沒了
companion object {
var c: Int = 0
}
}
複製代碼
這就是這節最開始講到的,Java 靜態變量和方法的等價寫法:companion object
變量和函數。
靜態初始化
Java 中的靜態變量和方法,在 Kotlin 中都放在了 companion object
中。所以 Java 中的靜態初始化在 Kotlin 中天然也是放在 companion object
中的,像類的初始化代碼同樣,由 init
和一對大括號表示:
🏝️
class Sample {
👇
companion object {
👇
init {
...
}
}
}
複製代碼
除了靜態函數這種簡便的調用方式,Kotlin 還有更方便的東西:「top-level declaration
頂層聲明」。其實就是把屬性和函數的聲明不寫在 class
裏面,這個在 Kotlin 裏是容許的:
🏝️
package com.hencoder.plus
// 👇 屬於 package,不在 class/object 內
fun topLevelFuncion() {
}
複製代碼
這樣寫的屬性和函數,不屬於任何 class
,而是直接屬於 package
,它和靜態變量、靜態函數同樣是全局的,但用起來更方便:你在其它地方用的時候,就連類名都不用寫:
🏝️
import com.hencoder.plus.topLevelFunction // 👈 直接 import 函數
topLevelFunction()
複製代碼
寫在頂級的函數或者變量有個好處:在 Android Studio 中寫代碼時,IDE 很容易根據你寫的函數前幾個字母自動聯想出相應的函數。這樣提升了寫代碼的效率,並且能夠減小項目中的重複代碼。
命名相同的頂級函數
頂級函數不寫在類中可能有一個問題:若是在不一樣文件中聲明命名相同的函數,使用的時候會不會混淆?來看一個例子:
在 org.kotlinmaster.library
包下有一個函數 method:
🏝️
package org.kotlinmaster.library1
👆
fun method() {
println("library1 method()")
}
複製代碼
在 org.kotlinmaster.library2
包下有一個同名函數:
🏝️
package org.kotlinmaster.library2
👆
fun method() {
println("library2 method()")
}
複製代碼
在使用的時候若是同時調用這兩個同名函數會怎麼樣:
🏝️
import org.kotlinmaster.library1.method
👆
fun test() {
method()
👇
org.kotlinmaster.library2.method()
}
複製代碼
能夠看到當出現兩個同名頂級函數時,IDE 會自動加上包前綴來區分,這也印證了「頂級函數屬於包」的特性。
那在實際使用中,在 object
、companion object
和 top-level 中該選擇哪個呢?簡單來講按照下面這兩個原則判斷:
object
或 companion object
。Java 中,除了上面講到的的靜態變量和方法會用到 static
,聲明常量時也會用到,那 Kotlin 中聲明常量會有什麼變化呢?
Java 中聲明常量:
☕️
public class Sample {
👇 👇
public static final int CONST_NUMBER = 1;
}
複製代碼
Kotlin 中聲明常量:
🏝️
class Sample {
companion object {
👇 // 👇
const val CONST_NUMBER = 1
}
}
const val CONST_SECOND_NUMBER = 2
複製代碼
發現不一樣點有:
const
關鍵字。除此以外還有一個區別:
緣由是 Kotlin 中的常量指的是 「compile-time constant 編譯時常量」,它的意思是「編譯器在編譯的時候就知道這個東西在每一個調用處的實際值」,所以能夠在編譯時直接把這個值硬編碼到代碼裏使用的地方。
而非基本和 String 類型的變量,能夠經過調用對象的方法或變量改變對象內部的值,這樣這個變量就不是常量了,來看一個 Java 的例子,好比一個 User 類:
☕️
public class User {
int id; // 👈 可修改
String name; // 👈 可修改
public User(int id, String name) {
this.id = id;
this.name = name;
}
}
複製代碼
在使用的地方聲明一個 static final
的 User 實例 user
,它是不能二次賦值的:
☕️
static final User user = new User(123, "Zhangsan");
👆 👆
複製代碼
可是能夠經過訪問這個 user
實例的成員變量改變它的值:
☕️
user.name = "Lisi";
👆
複製代碼
因此 Java 中的常量能夠認爲是「僞常量」,由於能夠經過上面這種方式改變它內部的值。而 Kotlin 的常量由於限制類型必須是基本類型,因此不存在這種問題,更符合常量的定義。
前面講的 val
「只讀變量」和靜態變量都是針對單個變量來講的,接下來咱們看看編程中另一個常見的主題:數組和集合。
聲明一個 String 數組:
Java 中的寫法:
☕️
String[] strs = {"a", "b", "c"};
👆 👆
複製代碼
Kotlin 中的寫法:
🏝️
val strs: Array<String> = arrayOf("a", "b", "c")
👆 👆
複製代碼
能夠看到 Kotlin 中的數組是一個擁有泛型的類,建立函數也是泛型函數,和集合數據類型同樣。
針對泛型的知識點,咱們在後面的文章會講,這裏就先按照 Java 泛型來理解。
將數組泛型化有什麼好處呢?對數組的操做能夠像集合同樣功能更強大,因爲泛型化,Kotlin 能夠給數組增長不少有用的工具函數:
get() / set()
contains()
first()
find()
這樣數組的實用性就大大增長了。
取值和修改
Kotlin 中獲取或者設置數組元素和 Java 同樣,可使用方括號加下標的方式索引:
🏝️
println(strs[0])
👇 👆
strs[1] = "B"
複製代碼
不支持協變
Kotlin 的數組編譯成字節碼時使用的仍然是 Java 的數組,但在語言層面是泛型實現,這樣會失去協變 (covariance) 特性,就是子類數組對象不能賦值給父類的數組變量:
Kotlin
🏝️
val strs: Array<String> = arrayOf("a", "b", "c")
👆
val anys: Array<Any> = strs // compile-error: Type mismatch
👆
複製代碼
而這在 Java 中是能夠的:
☕️
String[] strs = {"a", "b", "c"};
👆
Object[] objs = strs; // success
👆
複製代碼
關於協變的問題,這裏就先不展開了,後面講泛型的時候會提到。
Kotlin 和 Java 同樣有三種集合類型:List、Set 和 Map,它們的含義分別以下:
List
以固定順序存儲一組元素,元素能夠重複。Set
存儲一組互不相等的元素,一般沒有固定順序。Map
存儲 鍵-值 對的數據集合,鍵互不相等,但不一樣的鍵能夠對應相同的值。從 Java 到 Kotlin,這三種集合類型的使用有哪些變化呢?咱們依次看看。
List
Java 中建立一個列表:
☕️
List<String> strList = new ArrayList<>();
strList.add("a");
strList.add("b");
strList.add("c"); // 👈 添加元素繁瑣
複製代碼
Kotlin 中建立一個列表:
🏝️
val strList = listOf("a", "b", "c")
複製代碼
首先能看到的是 Kotlin 中建立一個 List
特別的簡單,有點像建立數組的代碼。並且 Kotlin 中的 List
多了一個特性:支持 covariant(協變)。也就是說,能夠把子類的 List
賦值給父類的 List
變量:
Kotlin:
🏝️
val strs: List<String> = listOf("a", "b", "c")
👆
val anys: List<Any> = strs // success
👆
複製代碼
而這在 Java 中是會報錯的:
☕️
List<String> strList = new ArrayList<>();
👆
List<Object> objList = strList; // 👈 compile error: incompatible types
👆
複製代碼
對於協變的支持與否,List
和數組恰好反過來了。關於協變,這裏只需結合例子簡單瞭解下,後面的文章會對它展開討論。
和數組的區別
Kotlin 中數組和 MutableList 的 API 是很是像的,主要的區別是數組的元素個數不能變。那在何時用數組呢?
這個問題在 Java 中就存在了,數組和 List
的功能相似,List
的功能更多一些,直覺上應該用 List
。但數組也不是沒有優點,基本類型 (int[]
、float[]
) 的數組不用自動裝箱,性能好一點。
在 Kotlin 中也是一樣的道理,在一些性能需求比較苛刻的場景,而且元素類型是基本類型時,用數組好一點。不過這裏要注意一點,Kotlin 中要用專門的基本類型數組類 (IntArray
FloatArray
LongArray
) 才能夠免於裝箱。也就是說元素不是基本類型時,相比 Array
,用 List
更方便些。
Set
Java 中建立一個 Set
:
☕️
Set<String> strSet = new HashSet<>();
strSet.add("a");
strSet.add("b");
strSet.add("c");
複製代碼
Kotlin 中建立相同的 Set
:
🏝️
val strSet = setOf("a", "b", "c")
複製代碼
和 List
相似,Set
一樣具備 covariant(協變)特性。
Map
Java 中建立一個 Map
:
☕️
Map<String, Integer> map = new HashMap<>();
map.put("key1", 1);
map.put("key2", 2);
map.put("key3", 3);
map.put("key4", 3);
複製代碼
Kotlin 中建立一個 Map
:
🏝️
val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)
複製代碼
和上面兩種集合類型類似建立代碼很簡潔。mapOf
的每一個參數表示一個鍵值對,to
表示將「鍵」和「值」關聯,這個叫作「中綴表達式」,這裏先不展開,後面的文章會作介紹。
取值和修改
Kotlin 中的 Map 除了和 Java 同樣可使用 get()
根據鍵獲取對應的值,還可使用方括號的方式獲取:
🏝️
👇
val value1 = map.get("key1")
👇
val value2 = map["key2"]
複製代碼
相似的,Kotlin 中也能夠用方括號的方式改變 Map
中鍵對應的值:
🏝️
👇
val map = mutableMapOf("key1" to 1, "key2" to 2)
👇
map.put("key1", 2)
👇
map["key1"] = 2
複製代碼
這裏用到了「操做符重載」的知識,實現了和數組同樣的「Positional Access Operations」,關於這個概念這裏先不展開,後面會講到。
可變集合/不可變集合
上面修改 Map
值的例子中,建立函數用的是 mutableMapOf()
而不是 mapOf()
,由於只有 mutableMapOf()
建立的 Map
才能夠修改。Kotlin 中集合分爲兩種類型:只讀的和可變的。這裏的只讀有兩層意思:
如下是三種集合類型建立不可變和可變實例的例子:
listOf()
建立不可變的 List
,mutableListOf()
建立可變的 List
。setOf()
建立不可變的 Set
,mutableSetOf()
建立可變的 Set
。mapOf()
建立不可變的 Map
,mutableMapOf()
建立可變的 Map
。能夠看到,有 mutable
前綴的函數建立的是可變的集合,沒有 mutbale
前綴的建立的是不可變的集合,不過不可變的能夠經過 toMutable*()
系函數轉換成可變的集合:
🏝️
val strList = listOf("a", "b", "c")
👇
strList.toMutableList()
val strSet = setOf("a", "b", "c")
👇
strSet.toMutableSet()
val map = mapOf("key1" to 1, "key2" to 2, "key3" to 3, "key4" to 3)
👇
map.toMutableMap()
複製代碼
而後就能夠對集合進行修改了,這裏有一點須要注意下:
toMutable*()
返回的是一個新建的集合,原有的集合仍是不可變的,因此只能對函數返回的集合修改。Sequence
除了集合 Kotlin 還引入了一個新的容器類型 Sequence
,它和 Iterable
同樣用來遍歷一組數據並能夠對每一個元素進行特定的處理,先來看看如何建立一個 Sequence
。
相似 listOf()
,使用一組元素建立:
🏝️
sequenceOf("a", "b", "c")
複製代碼
使用 Iterable
建立:
🏝️
val list = listOf("a", "b", "c")
list.asSequence()
複製代碼
這裏的 List
實現了 Iterable
接口。
使用 lambda 表達式建立:
🏝️ // 👇 第一個元素
val sequence = generateSequence(0) { it + 1 }
// 👆 lambda 表達式,負責生成第二個及之後的元素,it 表示前一個元素
複製代碼
這看起來和 Iterable
同樣呀,爲啥要畫蛇添足使用 Sequence
呢?在下一篇文章中會結合例子展開討論。
講完了數據集合,再看看 Kotlin 中的可見性修飾符,Kotlin 中有四種可見性修飾符:
public
:公開,可見性最大,哪裏均可以引用。private
:私有,可見性最小,根據聲明位置不一樣可分爲類中可見和文件中可見。protected
:保護,至關於 private
+ 子類可見。internal
:內部,僅對 module 內可見。相比 Java 少了一個 default
「包內可見」修飾符,多了一個 internal
「module 內可見」修飾符。這一節結合例子講講 Kotlin 這四種可見性修飾符,以及在 Kotlin 和 Java 中的不一樣。先來看看 public
:
public
Java 中沒寫可見性修飾符時,表示包內可見,只有在同一個 package
內能夠引用:
☕️ 👇
package org.kotlinmaster.library;
// 沒有可見性修飾符
class User {
}
複製代碼
☕️ // 👇 和上面同一個 package
package org.kotlinmaster.library;
public class Example {
void method() {
new User(); // success
}
}
複製代碼
☕️
package org.kotlinmaster;
// 👆 和上面不是一個 package
import org.kotlinmaster.library.User;
👆
public class OtherPackageExample {
void method() {
new User(); // compile-error: 'org.kotlinmaster.library.User' is not public in 'org.kotlinmaster.library'. Cannot be accessed from outside package
}
}
複製代碼
package
外若是要引用,須要在 class
前加上可見性修飾符 public
表示公開。
Kotlin 中若是不寫可見性修飾符,就表示公開,和 Java 中 public
修飾符具備相同效果。在 Kotlin 中 public
修飾符「能夠加,但不必」。
@hide
在 Android 的官方 sdk 中,有一些方法只想對 sdk 內可見,不想開放給用戶使用(由於這些方法不太穩定,在後續版本中頗有可能會修改或刪掉)。爲了實現這個特性,會在方法的註釋中添加一個 Javadoc 方法 @hide
,用來限制客戶端訪問:
☕️
/** * @hide 👈 */
public void hideMethod() {
...
}
複製代碼
但這種限制不太嚴格,能夠經過反射訪問到限制的方法。針對這個狀況,Kotlin 引進了一個更爲嚴格的可見性修飾符:internal
。
internal
internal
表示修飾的類、函數僅對 module 內可見,這裏的 module 具體指的是一組共同編譯的 kotlin 文件,常見的形式有:
咱們常見的是 Android Studio 中的 module 這種狀況,Maven project 僅做了解就好,不用細究。
internal
在寫一個 library module 時很是有用,當須要建立一個函數僅開放給 module 內部使用,不想對 library 的使用者可見,這時就應該用 internal
可見性修飾符。
Java 的 default
「包內可見」在 Kotlin 中被棄用掉了,Kotlin 中與它最接近的可見性修飾符是 internal
「module 內可見」。爲何會棄用掉包內可見呢?我以爲有這幾個緣由:
internal
「module 內可見」已經能夠知足對於代碼封裝的需求。protected
protected
表示包內可見 + 子類可見。protected
表示 private
+ 子類可見。Kotlin 相比 Java protected
的可見範圍收窄了,緣由是 Kotlin 中再也不有「包內可見」的概念了,相比 Java 的可見性着眼於 package
,Kotlin 更關心的是 module。
private
private
表示類中可見,做爲內部類時對外部類「可見」。private
表示類中或所在文件內可見,做爲內部類時對外部類「不可見」。private
修飾的變量「類中可見」和 「文件中可見」:
🏝️
class Sample {
private val propertyInClass = 1 // 👈 僅 Sample 類中可見
}
private val propertyInFile = "A string." // 👈 範圍更大,整個文件可見
複製代碼
private
修飾內部類的變量時,在 Java 和 Kotlin 中的區別:
在 Java 中,外部類能夠訪問內部類的 private
變量:
☕️
public class Outter {
public void method() {
Inner inner = new Inner();
👇
int result = inner.number * 2; // success
}
private class Inner {
private int number = 0;
}
}
複製代碼
在 Kotlin 中,外部類不能夠訪問內部類的 private
變量:
🏝️
class Outter {
fun method() {
val inner = Inner()
👇
val result = inner.number * 2 // compile-error: Cannot access 'number': it is private in 'Inner'
}
class Inner {
private val number = 1
}
}
複製代碼
能夠修飾類和接口
Java 中一個文件只容許一個外部類,因此 class
和 interface
不容許設置爲 private
,由於聲明 private
後沒法被外部使用,這樣就沒有意義了。
Kotlin 容許同一個文件聲明多個 class
和 top-level 的函數和屬性,因此 Kotlin 中容許類和接口聲明爲 private
,由於同個文件中的其它成員能夠訪問:
🏝️
private class Sample {
val number = 1
fun method() {
println("Sample method()")
}
}
// 👇 在同一個文件中,因此能夠訪問
val sample = Sample()
複製代碼
Walker(張磊) ,即刻 Android 高級工程師。2015 年加入即刻,參與了即刻 2.0 到 6.0 版本的架構設計和產品迭代。多年 Android 開發經驗,曾就任於 OPPO,專一於客戶端用戶體驗、音視頻開發和性能優化。