Visibility of Top-Level Declarations

In Cangjie, access modifiers can be used to control the visibility of top-level declarations such as types, global variables and global functions, known collectively as package members. There are four access modifiers in Cangjie: private, internal, protected, and public. The semantics of different access modifiers for top-level entities is as follows:

  • private members are visible only in the current file and cannot be accessed from other files.
  • internal members are visible only in the current package and its subpackages (including nested subpackages). These members can be accessed from the same package without being imported or from subpackages of the current package through imports.
  • protected members are visible only in the current module. Files in the same package can access these members without imports. Packages in the same module can access them through imports, but packages in different modules cannot access them.
  • public members are visible both inside and outside the module. Files in the same package can access these members without imports, and other packages can access them through imports.
ModifierFilePackage and SubpackageModuleAll Packages
privateYNNN
internalYYNN
protectedYYYN
publicYYYY

The package declaration and import declarations may also have access modifiers discussed later in this chapter. The rules for access modifiers and default modifiers supported by different top-level declarations are as follows (The default modifiers can be explicitly specified, and are used when no access modifiers are specified):

  • package: supports internal, protected, and public, with public being the default modifier.
  • import: supports all access modifiers, with private being the default modifier.
  • Other top-level declarations support all access modifiers, with internal being the default modifier.
package a

private func f1() { 1 }   // f1 is visible only in the current file.
func f2() { 2 }           // f2 is visible only in the current package and its subpackages.
protected func f3() { 3 } // f3 is visible only in the current module.
public func f4() { 4 }    // f4 is visible both inside and outside the current module.

The hierarchy of access levels in Cangjie is as follows: public > protected > internal > private. The level of the access modifier of a declaration cannot be higher than that of an entity used in the declaration. The following are some examples:

  • Parameters and return values in a function declaration:

    // a.cj
    package a
    class C {}
    public func f1(a1: C) // Error, public declaration f1 cannot use internal type C.
    {
        return 0
    }
    public func f2(a1: Int8): C // Error, public declaration f2 cannot use internal type C.
    {
        return C()
    }
    public func f3 (a1: Int8) // Error, public declaration f3 cannot use internal type C.
    {
        return C()
    }
    
  • Variable declaration:

    // a.cj
    package a
    class C {}
    public let v1: C = C() // Error, public declaration v1 cannot use internal type C.
    public let v2 = C() // Error, public declaration v2 cannot use internal type C.
    
  • Inherited type in a class declaration:

    // a.cj
    package a
    open class C1 {}
    public class C2 <: C1 {} // Error, public declaration C2 cannot use internal type C1.
    
  • Interface for implementing a class:

    // a.cj
    package a
    interface I {}
    public enum E <: I { A } // Error, public declaration uses internal types.
    
  • Type argument of a generic type:

    // a.cj
    package a
    public class C1<T> {}
    class C2 {}
    public let v1 = C1<C2>() // Error, public declaration v1 cannot use internal type C2.
    
  • Upper bound of a class in the where constraint:

    // a.cj
    package a
    interface I {}
    public class B<T> where T <: I {}  // Error, public declaration B cannot use internal type I.
    

At the same time, however:

  • public-modified declarations can use any classes visible in the package in their initialization expressions or function bodies, including public-modified classes and non-public -modified classes:

    // a.cj
    package a
    class C1 {}
    func f1(a1: C1)
    {
      return 0
    }
    public func f2(a1: Int8) // Ok.
    {
      var v1 = C1()
      return 0
    }
    public let v1 = f1(C1()) // Ok.
    public class C2 // Ok.
    {
      var v2 = C1()
    }
    
  • public-modified top-level declarations can use anonymous functions or any top-level functions, including public-modified classes and non-public-modified top-level functions.

    public var t1: () -> Unit = { => } // Ok.
    func f1(): Unit {}
    public let t2 = f1 // Ok.
    
    public func f2() // Ok.
    {
      return f1
    }
    
  • Built-in types such as Rune and Int64 are also modified by public by default.

    var num = 5
    public var t3 = num // Ok.