ClassesΒΆ

View classes.chpl on GitHub

This primer covers the declaration and use of classes.

A class is a type that can contain variables and constants, called fields, as well as functions and iterators called methods. A new class type is declared using the class keyword.

class C {
  var a, b: int;
  proc printFields() {
    writeln("a = ", a, " b = ", b);
  }
}

Class variables can be declared using the new keyword to call the constructor for the class C. The default constructor has an argument for each field in the class. Once a class has been constructed, its methods can be called.

var foo = new C(1, 2);
foo.printFields();

Default output is supported so a class can be written by making a call to write or writeln. Default input is also supported.

writeln(foo);

Methods can also be defined outside of the class body by prefixing the method name with the class name. All methods have an implicit this argument that is a reference to the class instance, or object. The this argument can be used to access a field explicitly. For example, in the method below, the this argument is used to access the b field which is otherwise shadowed by the b argument.

proc C.sum_a_b_b(b: int) {
  return a + b + this.b;
}
writeln(foo.sum_a_b_b(3));

Here, a class named D is declared as a derived class from C. This new class has all of the fields and methods from C, plus any additional fields or methods it declares. The printFields method has the same signature as a method from C -- it is overridden.

class D: C {
  var c = 1.2, d = 3.4;
  proc printFields() {
    writeln("a = ", a, " b = ", b, " c = ", c, " d = ", d);
  }
}

The static type of the variable foo, declared above, is C. Because the class D is derived from C, the variable foo can reference an object of type D. If an overridden method such as printFields is called, it is dynamically dispatched to the method with the most specific dynamic type. The delete keyword can be used to free memory associated with foo before pointing it an instance of D.

delete foo;
foo = new D(3, 4);
foo.printFields();
delete foo;

There are a few method names that cause the method to have special meaning. A method named this allows a class to be indexed like an array. A method named these allows a class to be iterated over.

class ArrayLike {
  var a, b, c, d: int;
  proc this(i:int) ref {
    select i {
      when 1 do return a;
      when 2 do return b;
      when 3 do return c;
      when 4 do return d;
      otherwise halt("index out of bounds", i);
    }
  }

  iter these() ref {
    yield a;
    yield b;
    yield c;
    yield d;
  }
}

This ArrayLike object can be indexed like a 4 element array and it can be iterated over in a loop.

var a = new ArrayLike();
a(2) = 1; // call to this method
a(4) = 2; // call to this method

for elt in a do // invocation of these iterator
  writeln(elt);
delete a;