ECMAScript 4 Netscape Proposal
Core Language
Classes
previousupnext

Monday, April 28, 2003

Class Definitions

Classes are defined using the class keyword.

ClassDefinition  class Identifier Inheritance Block
Inheritance 
   «empty»
|  extends TypeExpressionallowIn

Like other definitions, a class definition may be preceded by one or more attributes, which affect the class’s scope, namespace, and semantics. Every class is also a value and has type Type.

A class definition may only be located at a scope that allows class definitions, defined as follows:

According to these rules, a class may not be defined inside a function or a compound statement other than a block. If a class B is defined as a member of another class A, then B must be declared static.

Superclasses

A class may have a superclass specified by its extends clause. If omitted, the superclass defaults to Object. The superclass TypeExpression must be a compile-time constant expression without forward references.

A class is a subtype of its superclass.

Body

When a ClassDefinition is evaluated, the following steps take place:

  1. Create a new type t and bind the class’s QualifiedIdentifier to the constant t.
  2. The TypeExpression, if any, in the extends clause is evaluated, and t is made a subtype of its superclass. Any static members of t’s superclass are also defined as properties of the object t.
  3. A new, anonymous namespace for holding the class’s private members is constructed and used for the lexical extent of the Block.
  4. Block is evaluated using a new activation frame initialized with alias bindings for all most derived global members of the superclass. Any static and constructor members defined for Block’s activation frame are added as properties of the object t as they are being defined; these may hide static members inherited from superclasses.
  5. If Block is evaluated successfully (without throwing out an exception), all instance members defined for Block’s top-level scope (along with those inherited from superclasses) are collected to make a template for creating instances of type t.

A ClassDefinition’s Block is evaluated just like any other Block, so it can contain expressions, statements, loops, etc. Such statements that do not contain declarations do not contribute members to the class being declared, but they are evaluated when the class is declared.

Instance Members

A class C’s instance member id becomes a separate property of each instance of C. If c is an instance of C, then such a property can be accessed using the expression c.id. Instance members are inherited from the superclass.

If present, an initializer for a var or const instance member must be a compile-time constant expression.

Methods

A function instance member is called a method. A method may use this to refer to the object on which it was called. The value of this will always be an instance of the class or one of its subclasses. A method may not change the value of this.

A method is not in itself a value and has no type. There is no way to extract an undispatched method from a class. The . operator produces a function (more specifically, a closure) that is already dispatched and has this bound to the left operand of the . operator.

A method is called by combining the . operator with a function call. For example:

class C {
  var x:Integer = 3;
  function m() {return x}
  function n(x) {return x+4}
}

var c = new C;
c.m();                 //
returns 3
c.n(7);                //
returns 11
var f:Function = c.m;  //
f is a zero-argument function with this bound to c
f();                   //
returns 3
c.x = 8;
f();                   //
returns 8

Overriding

A class C may override a method m defined in its superclass s. To do this, C should define a method m' with the same name as m and use the override attribute in the definition of m'. Overriding a method without using the override attribute or using the override attribute when not overriding a method results in an error intended to catch misspelled method names.

The overriding method m' must have the same set of parameters that the overridden method m has.

Let p be any parameter. If m' does not specify a type for p, it inherits the type of p from m. If m' does specify a type for p, it must be the same type as that for p in m. If p is optional in m, then it must also be optional in m' with the same parameter name; however, the default value may differ.

If omitted, the return type of m' defaults to the return type of m. If supplied, the return type of m' must be the same as the return type of m.

A final method cannot be overridden (or further overridden) in the subclasses in which it is visible.

The overridden method m' is put in the same namespaces as method m.

Method m' may call method m using the super operator: either super.m(args) or super this.m(args).

A method may only override another method. An instance variable may only override another instance variable. A getter may override a getter or an instance variable. A setter may override a setter or an instance variable.

Static Members

A class C’s static member id becomes a property of the class object C. This member can be accessed using the expression C.id. static members are inherited from the superclass.

Inherited static variables have only one global value, not one value per subclass. For example, if class C has a static variable v and class D inherits from C, then v can be read or written either as C.v or as D.v; it’s the same variable rather than two separate variables.

Each instance member o named n of class C (other than members that are setters without a corresponding getter) also causes a global member g named n to be defined in C. That global member is currently inaccessible and reserved for a future language extension.

Constructors

A constructor is a function that creates a new instance of a class C. A constructor is defined as a method with the name C without any of the attributes static, virtual, or final. A constructor is invoked using the expression new C or new C(args).

A constructor can refer to its class’s instance variables via this. If a class C inherits from class B, then when B’s constructor is called while creating an instance of C, B’s constructor will be able to call virtual methods of class C on the partially constructed instance. Likewise, B’s constructor could store this into a global variable v and some other function could call a method of C on the partially constructed object v. Class C’s methods can be assured that they are only called on fully initialized instances of C only if neither C nor any of its ancestors contains a constructor that exhibits either of the behaviors above.

A constructor may invoke a return statement as long as that statement does not supply a value; a constructor cannot return a value. The newly created object is returned automatically. A constructor’s return type must be omitted. A constructor always returns a new instance.

A class named C must not define a static member with the name C in any namespace; such usage is reserved for a future extension.

If a class C does not define a constructor or a static function with the name C, a default constructor is automatically defined; that constructor takes the arguments that C’s superclass’s constructor takes, calls that superconstructor with those arguments, and initializes C’s new instance members to their default values.

Calling a Superconstructor

Let C be a class and B its superclass. C’s constructor must call B’s constructor before it accesses this or super or before it returns. The call can be either explicit or implicit; if C’s constructor does not contain any calls to B’s constructor, then a call to B’s constructor with no arguments is automatically inserted as the first statement of C’s constructor. C’s constructor does not have to call B’s constructor when it exits by throwing an exception. C’s constructor may not call B’s constructor again after it already called it.

C’s constructor calls B’s constructor using the statement super(args). This must be a complete statement; it means something different if it is a subexpression of a larger expression. It is not possible to skip class hierarchy levels while constructing an object — if C’s superclass is B and B’s superclass is A, then C’s constructor cannot directly call A’s constructor.


Waldemar Horwat
Last modified Monday, April 28, 2003
previousupnext