@c This document is part of the GNU ease.js manual. @c Copyright (C) 2014 Free Software Foundation, Inc. @c Permission is granted to copy, distribute and/or modify this document @c under the terms of the GNU Free Documentation License, Version 1.3 or @c any later version published by the Free Software Foundation; with no @c Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. @c A copy of the license is included in the section entitled ``GNU Free @c Documentation License''. @node Interoperability @chapter Interoperability GNU ease.js is not for everyone, so it is important to play nicely with vanilla ECMAScript so that prototypes and objects can be integrated with the strict restrictions of ease.js (imposed by classical OOP). In general, you should not have to worry about this: everything is designed to work fairly transparently. This chapter will go over what ease.js intentionally supports and some interesting concepts that may even be useful even if you have adopted ease.js for your own projects. @menu * Using GNU ease.js Classes Outside of ease.js:: * Prototypally Extending Classes:: @end menu @node Using GNU ease.js Classes Outside of ease.js @section Using GNU ease.js Classes Outside of ease.js GNU ease.js is a prototype generator---it takes the class definition, applies its validations and conveniences, and generates a prototype and constructor that can be instantiated and used just as any other ECMAScript constructor/prototype. One thing to note immediately, as mentioned in the section @ref{Defining Classes,,Defining Classes}, is that constructors generated by ease.js may be instantiated either with or without the @code{new} keyword: @float Figure, f:interop-new @verbatim var Foo = Class( { /*...*/ } ); // both of these are equivalent Foo(); new Foo(); @end verbatim @caption{Constructors generated by ease.js may omit the @code{new} keyword} @end float ease.js convention is to omit the keyword for more concise code that is more easily chained, but you should follow the coding conventions of the project that you are working on. @node Prototypally Extending Classes @section Prototypally Extending Classes Since @ref{Classes,,classes} are also constructors with prototypes, they may be used as part of a prototype chain. There are, however, some important considerations when using any sort of constructor as part of a prototype chain. Conventionally, prototypes are subtyped by using a new instance as the prototype of the subtype's constructor, as so: @float Figure, f:interop-protochain-incorrect @verbatim var Foo = Class( { /*...*/ } ); // extending class as a prototype function SubFoo() {}; SubFoo.prototype = Foo(); // INCORRECT SubFoo.prototype.constructor = SubFoo; @end verbatim @caption{Incorrectly prototypally extending GNU ease.js classes} @end float The problem with this approach is that constructors may perform validations on their arguments to ensure that the instance is in a consistent state. GNU ease.js solves this problem by introducing an @code{asPrototype} method on all classes: @float Figure, f:interop-protochain @verbatim var Foo = Class( { /*...*/ } ); // extending class as a prototype function SubFoo() { // it is important to call the constructor ourselves; this is a // generic method that should work for all subtypes, even if SubFoo // implements its own __construct method this.constructor.prototype.__construct.apply( this, arguments ); // OR, if SubFoo does not define its own __construct method, you can // alternatively do this: this.__construct(); }; SubFoo.prototype = Foo.asPrototype(); // Correct SubFoo.prototype.constructor = SubFoo; @end verbatim @caption{Correctly prototypally extending GNU ease.js classes} @end float The @code{asPrototype} method instantiates the class, but does not execute the constructor. This allows it to be used as the prototype without any issues, but it is important that the constructor of the subtype invokes the constructor of the class, as in @ref{f:interop-protochain}. Otherwise, the state of the subtype is undefined. Keep in mind the following when using classes as part of the prototype chain: @itemize @item GNU ease.js member validations are not enforced; you will not be warned if an abstract method remains unimplemented or if you override a non-virtual method, for example. Please exercise diligence. @item It is not wise to override non-@ref{Inheritance,,virtual} methods, because the class designer may not have exposed a proper API for accessing and manipulating internal state, and may not provide proper protections to ensure consistent state after the method call. @item Note the @ref{Private Member Dilemma} to ensure that your prototype works properly in pre-ES5 environments and with potential future ease.js optimizations for production environments: you should not define or manipulate properties on the prototype that would conflict with private members of the subtype. This is an awkward situation, since private members are unlikely to be included in API documentation for a class; ease.js normally prevents this from happening automatically. @end itemize