1
0
Fork 0
easejs/test/Trait
Mike Gerwitz d9b86c1544
Support for trait class supertype overrides
Traits can now override methods of their class supertypes.  Previously, in
order to override a method of some class `C` by mixing in some trait `T`,
both had to implement a common interface.  This had two notable downsides:

  1. A trait that was only compatible with details of `C` could only work
     with `C#M` if it implemented an interface `I` that declared `I#M`.
     This required the author of `C` to create interfaces where they would
     otherwise not be necessary.

  2. As a corollary of #1---since methods of interfaces must be public, it
     was not possible for `T` to override any protected method of `C`; this
     meant that `C` would have to declare such methods public, which may
     break encapsulation or expose unnecessary concerns to the outside
     world.

Until documentation is available---hopefully in the near future---the test
cases provide detailed documentation of the behavior.  Stackable traits work
as you would expect:

```javascript
var C = Class(
{
    'virtual foo': function()
    {
        return 'C';
    },
} );

var T1 = Trait.extend( C,
{
    'virtual abstract override foo': function()
    {
        return 'T1' + this.__super();
    },
} );

var T2 = Trait.extend( C,
{
    'virtual abstract override foo': function()
    {
        return 'T2' + this.__super();
    },
} );

C.use( T1 )
    .use( T1 )
    .use( T2 )
    .use( T2 )
    .foo();
// result: "T2T2T1T1C"
```

If the `override` keyword is used without `abstract`, then the super method
is statically bound to the supertype, rather than being resolved at runtime:

```javascript
var C = Class(
{
    'virtual foo': function()
    {
        return 'C';
    },
} );

var T1 = Trait.extend( C,
{
    'virtual abstract override foo': function()
    {
        return 'T1' + this.__super();
    },
} );

var T2 = Trait.extend( C,
{
    // static override
    'virtual override foo': function()
    {
        return 'T2' + this.__super();
    },
} );

C.use( T1 )
    .use( T1 )
    .use( T2 )
    .use( T2 )
    .foo();
// result: "T2C"
```

This latter form should be discouraged in most circumstances (as it prevents
stackable traits), but the behavior is consistent with the rest of the
system.

Happy hacking.
2015-10-24 23:53:23 -04:00
..
AbstractTest.js [copyright] Copyright update 2015-05-28 01:01:51 -04:00
ClassExtendTest.js Support for trait class supertype overrides 2015-10-24 23:53:23 -04:00
ClassVirtualTest.js Moved class virtual param test into ClassVirtualTest case 2014-05-02 20:13:41 -04:00
DefinitionTest.js [copyright] Copyright update 2015-05-28 01:01:51 -04:00
ImmediateTest.js [copyright] Copyright assignment to the FSF 2014-04-09 19:05:07 -04:00
LinearizationTest.js [copyright] Copyright assignment to the FSF 2014-04-09 19:05:07 -04:00
MixedExtendTest.js [copyright] Copyright assignment to the FSF 2014-04-09 19:05:07 -04:00
NamedTest.js [copyright] Copyright update 2015-05-28 01:01:51 -04:00
ParameterTest.js [copyright] Copyright update 2015-05-28 01:01:51 -04:00
PropertyTest.js [copyright] Copyright assignment to the FSF 2014-04-09 19:05:07 -04:00
ScopeTest.js [copyright] Copyright assignment to the FSF 2014-04-09 19:05:07 -04:00
VirtualTest.js Corrected virtual non-overridden trait method invocations 2014-05-02 21:08:41 -04:00