Class Declaration

A class declaration stores a class under an identifier. The identifier can be used to create an instance of the class.

Regular Class

The class body may only contain function and variable declarations. Declarations can be prefixed with static to declare them as static. Variables don't have to be assigned immediately if it is assigned in the constructor.

When a class is instantiated using the new keyword the constructor of the class will be called. If a class extends another class the super class must be called before being able to access this. This can be done by calling super and optionally providing arguments. If there is no constructor the constructor of the super class will automatically be called.

this is not available inside static functions and when declaring a static variable. A static variable can reference a different static variable by accessing the property through the class name. Inside non-static functions or when declaring a non-static variable different non-statics can be accessed by using this.

A class can extend multiple other classes. If there is a naming collision with methods from the classes that are being extended then the class needs to override the method. A naming collision occurs when two methods with the same parameter count or a variable have the same name on the same level of extending.

Abstract Class

A class can be made abstract by prefixing it with the abstract keyword. Abstract classes can't be instantiated directly, but must be extended by a regular class.

An abstract classs can make a property abstract by prefixing the property with abstract. If a property is abstract it can not contain an implementation. The class extending the abstract class must implement all abstract properties.

In Syntek a property can be both static and abstract.

Structure

Modifier = 'abstract' | 'static'

ClassProp = Modifier* Declaration
Constructor = 'new' ParamList Block

ClassBody = '{' ( ClassProp | Constructor )* '}'
Extends = 'extends' VarLoc ( ',' VarLoc )*

ClassDecl = 'abstract'? 'class' Identifier GenericParams? Extends? ClassBody

Example

Regular class:

class MyClass {
  var language = 'Syntek'

  function toString(): String {
    return this.language
  }
}

class Child extends MyClass {
  static var x: Number = 5
  static var y: Number = 15
}

class Horse extends Animal, Rideable {
  function ride() {
    print('Riding the horse')
  }
}

class Goldfish extends Fish, Pet {
  function feed() {
    print('Feeding the goldfish')
  }
}

class A {
  function toString(): String {
    return 'Class A'
  }
}

class B {
  function toString(): String {
    return 'Class B'
  }
}

class C extends A, B {
  function toString(): String { # override because of naming collision
    return A.super.toString() # this calls toString on A
  }
}

# LinkedList
class Node<T> {
  var data: T
  var next: Optional<Node<T>>
  var previous: Optional<Node<T>>

  new(data: T) {
    this.data = data
    this.next = Optional.empty()
    this.previous = Optional.empty()
  }
}

class LinkedList<T> {
  var head: Node<T>

  new() {
    this.head = new Node<T>()
  }
}

Abstract class:

abstract class Shape {
  var width: Number
  var height: Number

  new(width: Number, height: Number) {
    this.width = width
    this.height = height
  }

  abstract function display()

  abstract function calculateArea(): Number
}

abstract class Serializable<T> {
  abstract function serialize(): String

  static abstract function deserialize(value: String): T
}

References