Tya v0.7 Specification

This document is the specification for Tya v0.7 after v0.6 class-level members and instance field defaults.

Theme

Tya v0.7 is about single inheritance for instance behavior.

v0.5 adds minimal classes and objects. v0.6 adds class variables, class methods, and instance field defaults. v0.7 lets one class reuse and specialize another class's instance fields, initializer, and instance methods.

Goals

Included in v0.7

v0.7 includes all v0.6 class behavior and adds:

Not Included in v0.7

v0.7 does not include:

Extending a Class

A class may extend one parent class.

class User
  name = ""

  init = name ->
    @name = name

  greeting = ->
    "Hello, {@name}"

class Admin extends User
  role = "admin"

Admin is a subclass of User. It inherits User's instance field defaults and instance methods.

admin = Admin("komagata")
print admin.name
print admin.role
print admin.greeting()

Multiple inheritance is invalid.

class Bad extends User, Account

Constructor Behavior

If a subclass does not define init, its constructor uses the nearest inherited init.

class User
  init = name ->
    @name = name

class Admin extends User

admin = Admin("komagata")
print admin.name

If a subclass defines init, it is responsible for calling the parent init with super(args...) when the parent has one.

class Admin extends User
  init = name, role ->
    super(name)
    @role = role

There is no implicit argument forwarding from a subclass init to a parent init.

If a subclass defines init and the parent class defines init, omitting super(args...) is an error.

class Admin extends User
  init = name ->
    @name = name

The Admin initializer is invalid because User.init is not called.

Field Defaults and Inheritance

Instance field defaults are applied from parent to child before init runs.

class User
  active = true

class Admin extends User
  role = "admin"

admin = Admin()
print admin.active
print admin.role

A subclass may override a parent field default by declaring the same field name.

class User
  role = "user"

class Admin extends User
  role = "admin"

The subclass default wins for instances of the subclass.

Method Inheritance

Instance methods are inherited by subclasses.

class User
  greeting = ->
    "Hello"

class Admin extends User

admin = Admin()
print admin.greeting()

A subclass may override an inherited instance method by declaring a method with the same name.

class User
  greeting = ->
    "Hello"

class Admin extends User
  greeting = ->
    "Admin"

The subclass method is used for subclass instances.

super in Instance Methods

Inside an overridden instance method, super(args...) calls the parent method with the same name.

class User
  greeting = ->
    "Hello, {@name}"

class Admin extends User
  greeting = ->
    "{super()} (admin)"

super(args...) must be called explicitly with parentheses when there are no arguments.

super()

There is no super.greeting() form in v0.7.

Override Rules

An overriding instance method must use the same arity as the parent method.

class User
  rename = name ->
    @name = name

class Admin extends User
  rename = first_name, last_name ->
    @name = first_name + " " + last_name

The Admin.rename override is invalid because the arity differs from User.rename.

Return values are not checked beyond existing runtime behavior because v0.7 has no type annotations.

Class-Level Members and Inheritance

v0.7 inheritance applies to instance behavior only.

Class variables and class methods are not inherited in v0.7.

class User
  @@count = 0

  @@count_users = ->
    @@count

class Admin extends User

print User.count
print User.count_users()

Admin.count and Admin.count_users() are not part of v0.7 unless Admin declares its own class variable or class method.

This keeps @@field simple and avoids shared class-variable behavior across inheritance chains.

Modules and Inheritance

A class may extend a class from an imported module.

# user.tya
module user
  class User
    init = name ->
      @name = name

    greeting = ->
      "Hello, {@name}"
import user

class Admin extends user.User
  greeting = ->
    "{super()} (admin)"

Classes declared inside a module can also extend another class declared in the same module.

module accounts
  class User
    name = ""

  class Admin extends User
    role = "admin"

v0.7 does not import module classes directly into the local namespace.

Dot Access Boundary

Dot access keeps the v0.6 meanings:

v0.7 also allows a module class path in an extends clause:

class Admin extends user.User

Dictionaries continue to use bracket access.

profile = {"name": "komagata"}
print profile["name"]

Dictionary member access with profile.name is not part of v0.7.

Naming

Class names use PascalCase.

class User
class AdminUser
class HttpClient

Variables, functions, methods, fields, class variables, modules, files, and dictionary keys keep using snake_case.

Diagnostics

v0.7 implementations should report source-oriented errors for: