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
| Modifier | Meaning |
|---|---|
private | the current lexical scope and sub-scopes nested below it (member position only) |
internal | visible within the module (sibling files merged via partial see each other) |
derived | visible along the inheritance chain only (member position only) |
package | visible within the current package |
public | visible 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 secretWithin 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;
}hookChild 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.
