Tuesday, December 30, 2014

Object Oriented JavaScript - part 3

When I think about it, this project is getting really interesting. The more of this documentation I write, the more changes I make to the library. The more changes I make, the closer the library comes to being a complete Java class substitute in JavaScript. In preparation for this entry, I've added support for calling functions against the base class as well as interfaces.

While it's not the type of inheritance JS users are accustom to when using some form of extend(), I never really thought that version of inheritance was of much use. There isn't any real way to ensure that mixing 2 or more objects together won't cause errors in other code that isn't expecting the mix. What's more is that this form of mixing fails if the destination object being mixed in contains properties using calculations or is sealed or frozen.

I won't go into the reasons why multiple inheritance has been frowned on by so many leaders in the industry. It's not that I agree with that line of thinking either. However, prototype inheritance doesn't really lend itself to multiple inheritance. Where prototypes are concerned, there can be only 1. Any attempt to implement multiple inheritance would have to be in the form of a "has-a" relationship vs the "is-a" relationship that's normally expected with inheritance. While there is a way around this, I'm still working out the details. For now, let's talk about how the existing inheritance policy works.

Inheritance

Here's an example to get us started. This example shows an example of basic inheritance in Java and its equivalent in JS using Class.js.

Java

public class SampleBase {
    ...
}

public class Sample extends SampleBase {
    ...
}

Class.js

var SampleBase = new Class("SampleBase", {
    ...
});

var Sample = new Class("Sample", {
    Extends: SampleBase,
    ...
});

Much like Java, Class.js uses the word Extends to introduce a base class. This should not in any way be confused with the extend() method commonly employed by most other class libraries. This Extends element allows the object to properly inherit the prototype of the specified Class definition. That is to say, the object assigned as the Extends element in the class definition object must itself be a constructor as returned by new Class(...).

As yet, Class.js definition objects cannot inherit from objects defined by other class libraries or other constructor functions. This is primarily because no other library as yet possesses the facilities to provide private and protected scopes that are compatible with Class.js. In fact, no other class libraries currently possess the facilities to create protected scopes at all! This feature is currently unique to Class.js. Not even the current ES6 recommendations support this capability!

Suppose SampleBase had a public or protected memeber "foo". As expected, all public and protected members of SampleBase would be available to Sample instances through the "this" keyword. Likewise, as expected, protected members of Sample and SampleBase will not appear to exist on the variable returned by calling new Sample().

Since neither Sample nor SampleBase declare Constructor functions, this code will run just fine, but what happens if SampleBase declares a constructor?

this.Super

If a constructor is declared by the base class, it is not called automatically. Why? There's no way to know what parameters to pass it! Class.js leaves such issues to the developer and provides "this.Super" to facilitate the capability.
  • this.Super(<args>) - Calls the base class Constructor function. This should be the first function called by any derived class. It's optional if the base class doesn't declare Constructor, but as a matter of good form and practice, call it anyway.
  • this.Super.<member> - accesses any Protected or Public member of the base class, unmodified by the current derived class.
With "this.Super" you can access the base class version of a given member even if it has been overridden in the current class.

Interfaces

As I previously stated, prototype inheritance doesn't do multiple inheritance all that well. So, like with Java, the easiest thing to implement is Interface support. Here's the same example as before with interfaces added in.

Java

public interface foo {
    ...
}

public interface bar {
    ...
}

public interface fubar {
    ...
}

public class SampleBase {
    ...
}

public class Sample extends SampleBase implements foo, bar, fubar {
    ...
}

Class.js

var foo = { ... };
var bar = function() { ... };
bar.prototype = { ... };
var fubar = new Class("fubar", { ... });

var SampleBase = new Class("SampleBase", {
    ...
});

var Sample = new Class("Sample", {
    Extends: SampleBase,
    Implements: [ foo, bar, fubar ],
    ...
});

Once again, I borrowed from Java and used "Implements" as the key to list the interfaces implemented by the class. Behind the scenes, Class.js verifies that the public, enumerable interface exposed by each object in the Implements array has also been implemented in the class definition object. However, we run into that old multiple inheritance issue again. Given the code above, while in Java a Sample instance can be assigned to a variable of types foo, bar, and fubar, JS will not return true if you check (new Sample() instanceof foo). For Class.js, there is no way to do true multiple inheritance that can be recognized by the built-in JS operators.

<obj>.Implements(<arg>)

Since the built-in operators are insufficient and cannot be overridden without hacking the JS engine in use, the only thing left to do is to create new functions to do the same work. Implements() is such a function. This function performs the exact same check as was done for each element in the Implements array. The only argument is an object or function with a public interface. Implements() returns true if <obj>'s definition contains matching interfaces for all public parts of the argument.

As it stands, I'm still considering implementing full multiple inheritance using the same method. This means that instanceof() will no longer be useful, but that can be replaced by a factory method in Class.js. I wish there was some way of overloading the instanceof() function to support multiple inheritance.  With that, you can look forward to part 4 describing the tools available to you when implementing member functions in the class definition object. If I decide to implement multiple inheritance, I'll mention it then too.

Sunday, December 14, 2014

Object Oriented JavaScript - Part 2

Last time, I began with a rant. Well what did you expect? This is a blog about things bugging me, after all. On the hit list today is ECMAScript 6 (ES6). Why? Well, it seems they're finally getting around to implementing the "class" keyword. But before you jump for joy, it's just a thin shell over prototype inheritance. You don't get anything for it save for some syntactic sugar. All the real goodies of encapsulation are still no where to be found; still no private scopes, still no protected scopes.

I went on a search for Class.js on Google. I found six different versions, none of which was mine. That's to be expected though. I only released my version a few days ago. As for the other 6... well.... They all pretty much do the same thing, and still we get no real encapsulation. For me, this only further resolves my determination to complete all possible features of my Class.js library. Now, let's get down to the goods.

Class.js Usage

Class.js is built to be CommonJS compatible. However, it's also usable as a classic script tag include file. All you need to do is either require("Class") in your CommonJS environment or include script tags for the 4 library files, being sure to place Class.js last. After that, you're off to the races using full, Java-like class declarations in your code.

The Helper Functions

The keys to the syntax for using Class.js are the 6 helper functions that are members of the Class constructor function:
  • Class.Private
  • Class.Protected
  • Class.Public
  • Class.Static
  • Class.Final
  • Class.Property

When I use Class.js, I assign these 6 functions to local variables of the same name. That way, I don't have keep retyping "Class." on every member of the new class.

Example:

var Class = require('Class');
var Private = Class.Private;
var Protected = Class.Protected;
var Public = Class.Public;
var Static = Class.Static;
var Final = Class.Final;
var Property = Class.Property;

These 6 functions reproduce the corresponding scope and attribute keywords in Java. Java isn't exactly my favorite language, but given JS's original billing as Java's little brother.... Each of these functions has exactly the same declaration:

Class.??? = function(val) { ... };

These function are designed to take a single value that is either the value being assigned, or the return value from one of the other 5 functions. This allows multiple helpers to be used on a single member object. In this way, the helper functions act as wrappers to specify the scope of the object that was wrapped.

The ClassConstructor

The constructor has 2 parameters:
  • an optional first parameter for specifying the class name. If left blank, the class is an anonymous class.
  • a class definition object. This is where you will need the helper functions.

The Class Definition Object

This is where you define the actual layout of the class. What goes in here is not much different than what goes in to an equivalent Java class... save for the syntax of course. Here's an example class in Java, followed by the same class using Class.js.

Java Example:

class Book {
 private String bookType;
 private String name;
 private float size;
 private boolean onShelf;
 
 public Book(String name, float size) {
  this.name = name;
  this.size = size;
  this.bookType = "Book";
  this.onShelf = false;
 }
 
 protected void setBookType(String bookType) {
  this.bookType = bookType;
 }
 
 public void returnToShelf(Bookshelf bookshelf) {
  int shelf = bookshelf.shelfForBook(name);
  if (shelf >= 0) {
   List books = Array.asList(bookshelf.getBooksOnShelf(shelf));
   int index = books.indexOf(this);
   
   if (index >= 0)
    onShelf = true;
  }
 }

 public String getName() { return name; }
 public float getSize() { return size; }
 public String getBookType() { return bookType; }
}

Class.js:

var Book = new Class("Book", {
 _bookType: Private(),
 _name: Private(),
 _size: Private(0),
 _onShelf: Private(false),
 
 Constructor: Public(function Book(name, size) {
  this._name = name;
  this._size = size;
  this._bookType = "Book";
  this._onShelf = false;
 }),
 
 setBookType: Protected(function setBookType(bookType) {
  this._bookType = bookType;
 }),
 
 returnToShelf: Public(function returnToShelf(bookshelf) {
  var shelf = bookshelf.shelfForBook(this._name);

  if (shelf >= 0) {
   var books = bookshelf.getBooksOnShelf(shelf);
   int index = books.indexOf(this.Self);
   
   if (index >= 0)
    this._onShelf = true;
  }
 }),

 name: Public(Property({
  get: function() { return this._name; }
 })),
 size: Public(Property({
  get: function() { return this._size; }
 })),
 bookType: Public(Property({
  get: function() { return this._bookType; }
 }))
});

Save for the replacement of getXXX in the Java version with Properties in the JS version, these two classes are functionally equivalent. The privilege of every member of class Book is declared by wrapping its initializer using one of the appropriate helper functions. Notice that helper functions can be nested as well, as is the case when declaring properties. The only exceptions to this nesting capability are as follows:

  • Only 1 of Public, Private, and Protected can appear in a member declaration.
  • Protected and Static cannot be used together. Why? Consider this: a protected member is an inheritable member of the class and therefore part of the prototype (well, sort of...) while a static member exists on the class itself and is not at all part of the prototype. Where could I put that and keep both semantics?
  • Property and Final cannot be used together. Why? Properties are calculated values. Final values are constant. Who ever heard of a recalculated constant in programming?
  • Private, Static, and Property cannot be used together. Why? Any two of those together is ok, but when all three get together you wind up with a calculated value that is accessible on the class, but only to instances of that class. In essence, the use cases for this are identical to the use cases for private properties. Static becomes redundant, so there's no good reason I could come up with to allow it.
Feel free to disagree with me on any of the bottom 3 cases. If someone manages to convince me I'm wrong, I'll gladly change it.

Properties are internally set up using Object.defineProperty(), but there's a catch. Only the get and set elements of a property description are of any real use. The value element can be used, but the same result can be achieved without needing to use a property. The enumerable, configurable are hard coded to true and false, respectively. The writable flag is set automatically based on the helpers applied to the member.

Did you happen to notice that every reference to a member was preceded by the this keyword? That's just the nature of JS. Object members can only be accessed through their scopes. At the same time, did you notice that the use of the "this" keyword within the class always refers to the instance of that class? One of my goals was to make programming using Class.js as close to classical object oriented programming as possible without changing the language.

The constructor for any Class definition is always declared with the Constructor keyword. It doesn't have to be there, but beware! If you inherit from a class that has a Constructor, you need to include a Constructor as well! Remember, I implemented Java-style object inheritance. In Java, a subclass must call super() in its constructor before the class can be considered initialized. We'll get into more of the inheritance details in part 3.

Thursday, December 11, 2014

Object Oriented JavaScript - Part 1


With the various advancements in JavaScript/ECMAScript (I'm just going to call it JS from now on), it has gone from being a toy language only useful for putting small actions into web pages to being a language useful enough to write web services and desktop applications in. You can even write an entire application stack using just JS. To make things even more interesting, every week it seems someone comes up with yet another library for doing something a little, or even a lot easier in JS. The sheer power of JS is reflected in how quickly new libraries are cropping up making many things so much easier to do without incurring too much of a performance penalty. Remember, JS is still just a scripting language.

Background

One of the sore points for many JS developers is the seemingly weak support for objects. Sure, objects are first class entities, but the common notions of encapsulation and inheritance normally attributed to objects in other languages just aren't present. That's because JS is a prototype-oriented language as opposed to object-oriented in other object supporting languages. If you wanted to compare JS's object support to that of an object-oriented language, you'd call JS objects either instantiable namespaces or simply public structures.

What makes JS development interesting, however, is that functions are also first-class objects, in 2 different senses. First, the definition of a function is an object of type Function. Second, the runtime environment of a function is an object called a closure. Unlike normal objects, closures are more akin to private structures, whose members are only accessible to methods created in that closure. Between closures and objects, it is possible to construct objects in a fashion that more resembles ones found in object-oriented languages. However, the syntax for doing so is, well, less than elegant. Also, for all this trouble, there is no protected scope. So using this fairly standard method, we can have our objects and inheritance, but we lose out on some of the encapsulation.

The loss of encapsulation over inheritance and poor syntax aren't the only issues. The ever popular 'this' reference doesn't seem to be able to maintain its identity as a reference to an instance of the class unless you're really careful.

Other Solutions

While it may seem like I'm just ranting, I'm not the only one to see this as an issue. One of the developers at Microsoft cooked up TypeScript to solve this problem. It's not a bad solution, if you don't mind having to compile scripting code, that is. Also, there's the little issue about compatibility with existing JS libraries. There's a way to overcome those issues, creating declaration files that define the types TypeScript expects to know when looking at various library methods and values. This works for most cases as long as you can either find a pre-written definition that's current for the version of the library you're using, or write that definition yourself. I'll just leave it that this was not the solution for me.

How about CoffeeScript? Well, no. That, while it offers some interesting features, departs from Javascript syntax in an attempt to provide more syntatic sugar for common JS patterns. What does that mean? While it (arguably)improves on the syntax, you don't get much in the way of new functionality where objects are concerned. So once again, not the solution for me.

Prototype? Close, but no cigar. You have no idea how much I wanted this to be the solution. However, I still can't get a reasonably protected scope from it. Also, IMHO, you don't get much of a boost in the syntax for the features you get. Is it useful? Certainly, but it's just not far enough into the solution I was looking for. There are even more attempts to make a better class than these, but these are the top 3 on my list.

My Solution

After shopping around and coming out sorely disappointed, I started writing my own library. What should a class declaration look like? How can I use closures to make a functional protected scope? Like the Grinch, I puzzed and puzzed till my puzzler was sore. Then it hit me. To make a functional protected space that can be shared between classes, all I needed to do was somehow pass the object backwards through the inheritance chain and let the ancestor classes attach their own protected portions! Easier said than done. Took me 10 days to work out the final solution. The solution required WeakMap support, but there's a shim for that. So this should work in any ES5 compatible environment. I'm still working on ES4 compatibility. So without further ado:

The Class.js Library

There are 4 files in the library:

  • Class.js
  • WeakMap.js
  • Enum.js
  • Functor.js

Enum.js provides enumeration support. While not strictly identical to enums found in object oriented languages, I think this code provides something appropriate for JS. Functor.js basically does the same work as Function.bind() except that the binding can be altered and/or duplicated. WeakMap is the shim I spoke of before. Since there is no way of creating a perfect WeakMap in JS code, I settled for emulating the spec as closely as possible leaking only a GUID string for each element declared in the WeakMap. Short of that leak, the entire WeakMap spec is upheld.

The library can be used directly as <script> includes or via CommonJS. When using <script>, be sure that Class.js is last. The order of the other 3 is irrelevant. When using CommonJS, you need only require Class.JS unless you intend to directly make use of the other 3 objects.

Class.js Syntax

One of the things I wanted was an elegant syntax for creating classes that mimicked the syntax I'd grown accustom to in object-oriented languages. In most object-oriented languages, a class definition looks something like this:

class Sample {
   private static final SOME_CONSTANT = SOMEVALUE;
   private int instance_var;
   protected void doSomething() { ... }
   
   public Sample() { ... }
   public int doSomethingElse() { ... };
}

Now one of the problems with this in JS is that "class" is a keyword. It's completely unused, but it's reserved nonetheless. Then there's the privilege levels and status modifiers that precede the member declaration. Here's how the same thing looks using Class.js.

var Sample = new Class("Sample", {
   SOME_CONSTANT: Private(Static(Final(SOMEVALUE))),
   instance_var: Private(undefined),
   doSomething: Protected(function doSomething() { ... }),
   
   Constructor: Public(function() { ... }),
   doSomethingElse: Public(function doSomethingElse() { ... })
}

The two declarations are completely identical in meaning. With the help of Class.js, almost anything you can do in an object oriented language becomes possible in JS, and all without a transcompiler. I'll introduce the usage of this library in part 2.