9. Classes

Overview

Classes are the most basic kind of type:

  • Classes are scoped within a pod and globally identified with the qualified name podName::ClassName
  • Classes contain zero or more uniquely named slots
  • Classes always inherit from exactly one super class (sys::Obj is the sole exception to this rule)
  • Classes may inherit zero or more mixins

Classes are declared using the class keyword:

class MyNewClass {}

Class Modifiers

Classes may be annotated with the following modifiers:

  • public
  • internal
  • abstract
  • final
  • const

For example to declare an internal abstract class:

internal abstract class Foo {}

Protection

The public and internal keywords define the visibility of the class. A public class may be used by everyone in the system. An internal class is visible only to types within the declaring pod. If no protection keyword is specified, the class defaults to public.

Abstract Classes

Abstract classes are classes designed never to be instantiated directly. It is a compiler error to call the constructor of an abstract class. However abstract classes do have constructors for use by their subclasses.

Abstract classes may or may not contain abstract methods. Although all classes which contain abstract methods, must be declared abstract.

The opposite of an abstract class is called a concrete class.

Final Classes

Final classes cannot be subclassed. Any attempt to extend from a final class will result in a compiler error.

Const Classes

Const classes are immutable - once created, an instance is guaranteed to have no state changes. The following rules must be observed with const classes:

Many fundamental primitive classes are const including Bool, Int, Float, and Str. Const classes and immutability play an import role in thread safety.

Obj

The root of all classes is the Obj class. Obj is the only class which doesn't have a superclass itself.

Instances

Fantom uses a pure object oriented type system. This means that all variables are an object which is an instance of exactly one class.

Reflection

The Type class is used to represent a class at runtime. You can always get the class type of an object using the Type.of method:

Type t := Type.of(obj)

Since all objects are instances of a class, this Type object will always represent a class. Given a Type which represents a concrete class, you can create new instances reflectively:

t.make                   // use default make constructor
t.make(args)             // use make constructor with arguments
t.method("makeX").call   // lookup and use a named constructor