Skip to Content

Visibility

Visibility modifiers come in two domains: the top-level domain governs top-level declarations in a module, and the member domain governs type members.

The encapsulation units line up level by level: private for the type, internal for the module, package open within the package, public fully open to everyone outside.

The Five Modifiers

ModifierMeaning
privatethe current lexical scope and sub-scopes nested below it (member position only)
internalvisible within the module (sibling files merged via partial see each other)
derivedvisible along the inheritance chain only (member position only)
packagevisible within the current package
publicvisible everywhere

The top-level domain accepts only three tiers: internal < package < public; private / derived cannot be written at the top level. An unadorned top-level declaration defaults to package visibility. The member domain accepts all five tiers, and an unadorned member defaults to private.

internal: the Module Boundary

module App; internal func Secret() -> string => "module secret"; public func Api() -> string => "public face"; func main() -> int { print(Api(), Secret()); return 0; }
public face module secret

Within its own module, Secret is directly callable — internal’s scope is the module. Other modules cannot call it, even when they obtain the short name via import Extra.*;.

The same law applies across packages: the FQR fully qualified name does not bypass visibility either; a non-public member is inaccessible from another package.

derived: Visible Along the Inheritance Chain

A derived member is visible to derived classes and invisible to the outside — an inheritance channel crossing type boundaries:

class Base { derived func Hook() -> string => "hook"; } class Child : Base { public func Use() -> string => Hook(); } func main() -> int { print(new Child().Use()); return 0; }
hook

Child can call Hook; code outside the class cannot. The difference from internal: internal admits the whole module (regardless of type relationships), derived only the inheritance chain.

package and public

internal func Modi() -> string => "this module only"; package func Pkgi() -> string => "the whole package"; public func Open() -> string => "anyone at all";

Calling Pkgi() across modules within the same package is legal (module B referencing a package member of module A); across packages only public remains. When you publish as a library, public is the API surface.

Notes

  • visibility is written in the declaration prefix position: public func / internal val / public class; the combination order with static and attribute prefixes is fixed (attributes → visibility → static → the rest);
  • cross-type access to type members follows the member domain; within the same type, private reaches everything;
  • sibling files merged by partial module see each other’s internal members; the merge happens before visibility is determined.
Last updated on October 11, 2026