# Object-oriented JavaScript

JavaScript is a prototype-based object-oriented language. You can use Caplin Trader 4’s Topiarist library to model classes, interfaces, and inheritence in JavaScript. You should use Topiarist in preference to the Bootstrap.js methods `caplin.extend` and `caplin.implement`, the use of which is now deprecated. The `caplin.extend` and `caplin.implement` methods will be removed in a future major release of Caplin Trader.

## Topiarist library

Topiarist is the recommend library for writing object-oriented JavaScript in Caplin Trader 4.

For an overview of Topiarist, see the pages below:

* [Topiarist: A JavaScript OO library featuring mixins, interfaces, and multiple inheritance](http://bladerunnerjs.org/blog/topiarist/)
* [GitHub: Topiarist](https://github.com/BladeRunnerJS/topiarist)
* [BladeRunnerJS: Classes](http://bladerunnerjs.org/docs/concepts/classes/)
* [BladeRunnerJS: Interfaces](http://bladerunnerjs.org/docs/concepts/interfaces/)

## Bootstrap.js methods (deprecated)

This section provides an overview of writing object-oriented JavaScript using the deprecated methods `caplin.extend` and `caplin.implement`.

* [Declaring interfaces](#declaring-interfaces)
* [Implementing interfaces](#implementing-interfaces)
* [Extending classes](#extending-classes) 
  * [Calling super constructors](#calling-super-constructors)
  * [Overriding super methods](#overriding-super-methods)
* [Writing static classes and enums](#writing-static-classes-and-enums)

### Declaring interfaces

Declaring an interface is essentially the same as declaring a class. With interfaces though, it’s important to provide feedback when an arbitrary method has not been implemented. You can do that by using `br.util.Utility.interfaceMethod()`, within the body of each of your interface’s methods.

Using `Animal` as an example interface, your definition could look something like this:

```js
var brUtility = require('br/util/Utility');

function Animal() {
}

Animal.prototype.speak = function() {
    brUtility.interfaceMethod('novox.Animal' , 'speak');
};

Animal.prototype.getGender = function() {
    brUtility.interfaceMethod('novox.Animal' , 'getGender');
};

Animal.prototype.getLegCount = function()    {
    brUtility.interfaceMethod('novox.Animal' , 'getLegCount');
};

module.exports = Animal;
```

If another class implements the `Animal` interface, it must implement all its methods as well, or it will not be able to invoke them. For example, if a class implements `Animal`, but does not provide an implementation for the method `speak()`, any invocation to `speak` will throw an exception with the message "Unexpected exception (This is an interface method (novox.Animal.speak))".

### Implementing interfaces

You can implement an interface using the `caplin.implement` method. You can use `caplin.implement` to implement as many interfaces as you wish.

If we wanted to declare a `Quadruped` class that implements the `Animal` interface, we could do it like this:

```js
var Animal = require('novox/Animal');

function Quadruped(sGender) {
    this.m_sGender = sGender;
};
caplin.implement(Quadruped, Animal);

Quadruped.prototype.getLegCount = function() {
    return 4;
};

Quadruped.prototype.getGender = function() {
    return this.m_sGender;
};

module.exports = Quadruped;
```

Note that it’s important to implement the interface _before_ any method declarations for it to work properly. It’s also important to provide the actual JavaScript constructor functions to `caplin.implement` rather than the function names as strings. You may also notice the `Quadruped` class hasn’t implemented the `speak()` method, which effectively makes this an abstract class.

### Extending classes

You can extend a class using the `caplin.extend()` method. You should declare the class extension before you declare any of its methods.

As `Quadruped` is an abstract class, we are going to need to extend it to provide a concrete implementation. Let’s extend `Quadruped` to give us two concrete classes of `Quadruped`: `Cat` and `Dog`.

The `Cat` class:

```js
var Quadruped = require('novox/Quadruped');

function Cat(sGender) {
};
caplin.extend(Cat, Quadruped);

Cat.prototype.speak = function() {
    alert('Meow!');
}

module.exports = Cat;
```

The `Dog` class:

```js
var Quadruped = require('novox/Quadruped');

function Dog(sGender) {
}
caplin.extend(Dog, Quadruped);

Dog.prototype.speak = function() {
    alert('Woof!');
};

module.exports = Dog;
```

By extending the `Quadruped` class and implementing the remaining method from the `Animal` interface, each of these new classes is complete and we could create instances of them.

#### Calling super constructors

The JavaScript method `apply` allows us to call a super constructor while retaining the correct `this` pointer.

We can call the super `Quadruped` constructor from within the `Dog` and `Cat` constructors by calling `Quadruped.apply(this, arguments)`.

The rewritten `Dog` constructor:

```js
function Dog(sGender) {
    Quadruped.apply(this, arguments);
};
```

The rewritten `Cat` constructor:

```js
function Cat(sGender) {
    Quadruped.apply(this, arguments);
};
```

If we added any additional arguments at a later date, using the `arguments` keyword ensures that they would all be passed back to the `Quadruped` super-constructor without having to explicitly add them to the `apply()` method in each constructor.

#### Overriding super methods

The JavaScript method `call` allows us to call super methods while retaining the correct `this` pointer.

By default, our cats and dogs all have four legs, a feature that they inherit from the `Quadruped` class. If we wanted to allow for the occasional three-legged dog we might encounter, the following code would allow us to override `Quadruped.getLegCount` for three-legged dogs, but still call `Quadruped.getLegCount` for four-legged dogs:

```js
Dog.prototype.getLegCount = function() {
    if (this.is3LeggedDog()) {
        return 3;
    }
    return Quadruped.prototype.getLegCount.call(this);
};
```

### Writing static classes and enums

It may be useful to provide static classes and enums to complement particular classes and interfaces. You can write static classes and enums by adding properties and methods to a constructor function rather than to the constructor function’s prototype.

For example, we may want to provide an `AnimalGender` enum to be used in conjunction with the `Animal` interface:

```js
function AnimalGender() {
}

AnimalGender.MALE = 'male';
AnimalGender.FEMALE = 'female';

module.exports = AnimalGender;
```
