Skip to content
This repository was archived by the owner on Sep 9, 2019. It is now read-only.

Classmembers

Timm Friebe edited this page Jun 2, 2013 · 10 revisions

In XP Language, there are three different types of reference types: Classes, interfaces and enums. Most members may be declared in any three, but we'll focus on classes here.

```groovy public class Album { protected string $name;

public __construct(string $name= null) { $this.setName($name); }

public void setName(string $name) { $this.name= $name; } public string getName() { return $this.name; } }

</td><td valign="middle" width="40%">
Let's start with a simple value object representing an online picture album. We'll define an Album class with one member protected member and the public getter and setter for it. The class has no declared parent and thus extends from the default lang.Object class. The class is public, meaning it is part of the API.
</td></tr></table>

Because we're agile-minded, continuously delivering people (but sometimes forget our good manners), we remember we should've written a test first, so let's do that now. We'll be using the XP Framework's testing API for this, which means we need to subclass the `unittest.TestCase` class, add methods using the various assert...() methods and decorate them with the `@test` annotation.

<table><tr><td valign="middle" width="60%">
```groovy
class AlbumTest extends unittest.TestCase {

  [@test] void can_create() {
    new Album();
  }

  [@test] void create_without_name() {
    $this.assertEquals(null, new Album().getName());
  }

  [@test] void create_with_name() {
    $this.assertEquals('test', new Album('test').getName());
  }

  [@test] void change_name_name() {
    $album= new Album('test');
    $album.setName('changed');
    $this.assertEquals('changed', $album.getName());
  }
}
We've omitted the public modifier for both the class and for the methods (meaning: this is not part of the API, test cases and their methods are used by the unittest runner only). In reality, since public is the default, nothing has changed.

Annotations decorate the test methods, for which we've used the underscore naming pattern contrary to the camelCase version as in the public API since it reads better for unittests. Since test methods don't return anything, we use the "void" type.

Now that we have a tested version, we'll apply our first refactoring. Actually, we'll only be changing the code to be more concise, and because the compiler is inbetween, it's a merely visual change! We'll rewrite the Album using the so-called "compact" syntax. It will allow us to shorten the name accessor methods slightly.

```groovy public class Album { protected string $name;

public __construct(string $name= null) { $this.setName($name); }

public void setName($this.name) { } public self withName($this.name) -> $this; public string getName() -> $this.name; }

</td><td valign="middle" width="40%">
While not everyone agrees getters and setters are the way (and say we should be using properties instead), the former have made a lasting impression on most of us. So while we do have to write them in order to comply to the accessor method way, XP Language helps us keep them short and concise. While we're at it, we'll add some fluent interface in here by adding withName().
</td></tr></table>

Time for some features, now! An album should be able to contain any number of images, so we'll start with the most straight-forward implementation using an array of images, which is initially empty. We'll add accessors for manipulating this array and accessing its size as well as the underlying images. The public API for using the class now is something along the lines of `$album.addImage(new Image(...));` for adding and `$album.getImages()` for reading them back again. We quickly feel the need to other accessors like `numImages()` and `clearImages()`, and are again off typing lots of code.

<table><tr><td valign="middle" width="60%">
```groovy
public class Album {
  protected string $name;

  private var $_images= new util.collections.Vector<Image>();
  public util.collections.Vector<Image> images {
    get { return $this._images; }
    set { throw new lang.IllegalArgumentException('Unmodifyable'); }
  }

  public __construct(string $name= null) {
    $this.setName($name);
  }

  // Name accessors omitted for brevity
}
So this time around, we use a property and thus are able to use all the operations the Vector class provides for us instead of having to reimplement them: add() and elements(), but also clear() and size(), and possibly more. We use a private member for backing the public property and make it read-only by raising exceptions from its setter. Now are API reads along the lines of: $album.images.add(new Image()). Because the Vector class overloads array access and iteration, we can even use $album.images[0] and iteration with foreach.
Clone this wiki locally