1
0
Fork 0
easejs/doc/interop.texi

131 lines
5.1 KiB
Plaintext
Raw Normal View History

@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