Overview
本章主要介紹各語言中的包和訪問權限控制。
Java 篇
包
創建包
- Java 使用關鍵字
package
來聲明一個包。 - 包名中使用
.
作為路徑分隔符,且包路徑必須與源文件路徑相同。 - 包只能聲明在源文件開頭。
例:
package a.b;
class B {}
導入包
- Java 使用關鍵字
import
導入包。 - 可以使用通配符
*
,導入一個包下的所有類。 - 如果一個類中都是靜態成員的話,可以使用靜態導入
static import
導入該類的所有靜態成員,這樣使用時就不用指定類名了。 - 導入語句只能聲明在源文件開頭,包聲明之后。
導入指定的類
import a.b.B;
導入指定包下的所有類
import a.b.*;
靜態導入
static import a.b.B.*;
package-info
Java 中每個包都可以聲明一個名為 package-info.java
的源文件。該源文件主要在生成文檔時用于描述當前包的功能和作用,有時也可以用于定義僅在包中共享的靜態變量和靜態方法。
訪問權限
Java 中訪問權限分為四種:
-
public
- 適用于類,屬性,方法
- public 表示總是可見。如果用于修飾類,則一個源文件中只能有一個類聲明為 public。
-
private
- 適用于內部類,屬性,方法
- private 表示只在聲明范圍內可見,所以修飾類時只能修飾內部類。
-
friendly
- 適用于類,屬性,方法
- 默認訪問控制權限,又稱為 default,在同包中可見,使用時不用真的添加
friendly
或default
關鍵字。
-
protected
- 適用于類,屬性,方法
- protected 等于 friendly + 子類可見。
注意: Java 并沒有父包和子包的概念,即
a.b.c
和a.b
沒有任何關系,也不存在訪問控制權限的傳遞,所以a.b.c
中定義的類無法訪問a.b
中的類定義的私有成員。
Groovy 篇
包
創建包與導入包均與 Java 相同。
訪問權限
Groovy 中訪問權限分為四種:
-
public
- 適用于類,屬性,方法
- 默認訪問控制權限,可以省略,表示總是可見。和 Java 不一樣,Groovy 中一個源文件中可以有多個類聲明為 public。
-
private
- 適用于內部類,屬性,方法
- private 表示只在聲明范圍內可見,所以修飾類時只能修飾內部類。
-
protected
- 適用于類,屬性,方法
- protected 等于 friendly + 子類可見。
-
package
適用于類,屬性,方法
-
類似 Java 的默認權限,使用方式較為復雜,并不推薦。
package 權限的例子
定義一個包含 package 權限方法的類
package a.b class B { def foo() {} @PackageScope def packageFoo() {} }
使用以上類
package a class A { @CompileStatic def foo() { def b = new B()( b.foo() b.packageFoo() } }
調用包含 package 權限的類的方法必須被聲明為
@CompileStatic
,否則 package 權限會被忽略。
Groovy 中也沒有父包和子包的概念。
Scala 篇
包
創建包
- Scala 也使用關鍵字
package
來聲明一個包。 - 包名中使用
.
作為路徑分隔符,和 Java 不同包路徑無須與源文件路徑相同。 - 包可以聲明在任意位置。
使用塊聲明包
package A {
package B {
class B {
}
}
}
此時 A
和 A.B
包的成員對 class C
直接可見。
使用串聯式包名
package A.B.C {
class C {
}
}
此時 A
和 A.B
包的成員對 class C
并不直接可見。
使用頂部標記聲明在源文件開頭,對整個源文件有效
package A.B
package C
等同于
package A {
package B {
package C {}
}
}
導入包
- Scala 使用關鍵字
import
導入包。 - 可以使用通配符
_
,導入一個包下的所有類 - 可以使用選取器
{}
導入一個包下的某些類或者指定別名 - 導入語句可以放在任意位置,包括方法內部。
導入指定的類
import a.b.B
導入指定包下的所有類
import a.b._
使用選取器導入指定的類
import java.awt.{Color,Font}
使用選取器重命名選取的類
import java.util.{HashMap=>JavaHashMap}
包對象
- 包對象用于組織包內可見的常量和方法,而不用具體包含在某個 utils 對象中,通常這是更好的做法。
- 每個包都可以包含一個包對象
- 包對象會被編譯為對應包內的
package.class
類,所以通常做法是在對應包內建立一個名為package.scala
的類來管理包對象。
package object Constants {
val VERSION = "0.0.1"
}
訪問權限
Scala 中 的訪問權限比較復雜
-
public
- 適用于類,屬性,方法
- 默認訪問控制符,總是可見。一個源文件中可以包含多個 public 的類。
-
private
- 適用于內部類,屬性,方法
- private 表示只在當前聲明范圍內可見,所以修飾類時只能修飾內部類。與 Java 最大的不同是外部類是無法調用內部類的 private 成員的。
-
protected
- 適用于類,屬性,方法
- protected 表示僅子類可見,與 Java 完全不同。
-
scope
-
Scala 中可以結合以上的訪問控制符和scope符號
[]
來自定義訪問控制權限。自定義包作用域
package A.B.C { class C { private[C] def desc = "desc" //同包 private[B] def impress = "impress" //上一級包 } }
-
Scala 包支持嵌套,即下層可以直接訪問上層作用域的成員。但是如果使用了串聯式包名,則必須手動引入對應的包才能正常使用。而在 Java 中不同包名沒有任何直接關系。
Kotlin 篇
包
創建包
與 Java 相同。
導入包
與 Java 相同。但是 Kotlin 在導入包時可以指定別名。
指定別名
import foo.bar as b
val b = b()
b.bar()
默認包
如果一個 kotlin 源文件中沒有任何包聲明,則其當中的代碼均屬于默認包,導入時包名即為函數名
fun hello() {
println("hello, Default Package")
}
import hello
hello()
訪問權限
Kotlin 中訪問權限分為四種:
-
public
- 適用于類,屬性,方法
- public 表示總是可見。
-
private
- 適用于類,屬性,方法
- private 表示在聲明范圍及同模塊的子作用域內可見。
-
internal
- 適用于類,屬性,方法
- 默認作用域,同模塊中可見。
-
protected
- 適用于類,屬性,方法
- protected 表示 private + 子類可見,與 Java 完全不同。
模塊是 Kotlin 的一個特殊的概念,表示的是一個單獨的編譯單元,概念類似Maven中的模塊。
Summary
- Scala 的包聲明與其它語言都不一樣
- Scala 和 Kotlin 導入包時支持指定別名
- Scala 和 Kotlin 的訪問權限與另兩種有很大區別
文章源碼見 https://github.com/SidneyXu/JGSK 倉庫的 _22_package
小節