Skip to Content
Cloth

Inheritance

A class may extend one other class. Use an explicit envelope and name the base after :.

// Animal.co Animal() {} func Describe(): string { return "Animal"; }
// Dog.co class : Animal { Dog(): Animal() {} override func Describe(): string { return super.Describe() + ": dog"; } }

The base must be a visible class. Self-inheritance and inheritance cycles are invalid. Constructors are not inherited.

Base construction

Every declared derived constructor must explicitly select a constructor of its direct base. There is no automatic zero-argument base call.

Base-initializer arguments may use parameters, literals, and static functions. They cannot observe self, instance fields, or unqualified instance functions.

Construction allocates one complete object. Base arguments are evaluated from derived toward root. Field initializers and constructor bodies then execute from root toward derived, with each class’s fields initialized in declaration order before its body.

A private base constructor is inaccessible to a derived class.

Overrides and dispatch

Every public class instance function is virtual. A local function matching an inherited name and canonical parameter signature must use override. A marker without a matching class or interface contract is invalid.

Animal animal = Dog(); println(animal.Describe()); // Animal: dog

The static receiver type determines the available signature. The runtime object determines which override runs. Private and static functions are not virtual.

Calls on the current object during field initialization and construction bind directly to the declaration selected for the class being initialized. This prevents a derived override from observing incomplete derived state. Calls on unrelated objects retain normal dispatch.

Member lookup uses the nearest class declaring the requested name. That class’s declaration set hides same-named declarations farther up the base chain. Private members remain private to their declaring file; they do not become accessible merely through inheritance.

Calling a base implementation

super.Method(arguments) looks up a public instance function through the direct-base view and calls it without virtual dispatch for that call.

It requires an instance context and cannot be used in a base initializer. super.Field, super.StaticMethod(), and super(...) are invalid. A base function called this way can still make ordinary virtual calls in its body.

Abstract and sealed classes

// Shape.co abstract class { Shape() {} abstract func Area(): float; }

An abstract class cannot be constructed directly. It may contain ordinary functions and public bodyless abstract func declarations. A concrete subclass must implement every inherited abstract signature; an abstract subclass may defer them.

An abstract restatement of an inherited class or interface requirement uses abstract override func. super cannot call a bodyless abstract function.

sealed class { ... } prevents subclassing. A class cannot be both abstract and sealed. final override func prevents further overrides of that function while leaving it callable. final func without override is invalid.

Covariant results and references

An override may return a managed-reference type assignable to the inherited result: for example, Dog instead of Animal, or Dog instead of Animal?. It cannot add nullability or widen the result. Primitive, enum, struct, and void results must match exactly. Arrays remain invariant.

Derived references widen implicitly to base types, including compatible nullable forms. Reverse conversion uses checked casts.