uhop / dcl

Elegant minimalistic implementation of OOP with mixins + AOP in JavaScript for node.js and browsers.
http://www.dcljs.org/
Other
76 stars 10 forks source link

error weaving accessor supercalls through three-level inheritance #28

Closed wkeese closed 6 years ago

wkeese commented 6 years ago

I think this should work, but when defining the third class, dcl throws an error about this.myFunc being undefined:

var Stateful = dcl( {
    myFunc: function () { return 1; }
});

var Selection = dcl(Stateful, {
    selectionMode: dcl.prop({
        set: function (value) {
        },
        get: function () {
            return this.myFunc();
        }
    })
});

var Select = dcl(Selection, {
    selectionMode: dcl.prop({
        set: dcl.superCall(function (sup) {
            return function (value) {
                sup.call(this, value);
            };
        }),
        get: dcl.superCall(function (sup) {
            return sup.call(this);
        })
    })
});
uhop commented 6 years ago

Select.selectionMode.get is incorrect.

This is how it works:

'use strict';

const dcl = require('./dcl');

var Stateful = dcl( {
    myFunc: function () { return 1; }
});

var Selection = dcl(Stateful, {
    // set selectionMode(value) {},
    // get selectionMode() {
    //  return this.myFunc();
    // }
    selectionMode: dcl.prop({
        set: function (value) {
        },
        get: function () {
            return this.myFunc();
        }
    })
});

var Select = dcl(Selection, {
    selectionMode: dcl.prop({
        set: dcl.superCall(function (sup) {
            return function (value) {
                sup.call(this, value);
            };
        }),
        get: dcl.superCall(function (sup) {
            return function () {
                return sup.call(this);
            };
        })
    })
});

const t = new Select();
console.log(t.selectionMode);

Compare the last lines of Select.

BTW, you don't need to use dcl.prop() to defined simple getters/setters. You can use the standard way as shown in the commented out code in Selection.

wkeese commented 6 years ago

Woops! Sorry about that, I didn't realize I had made a typo.

I'll keep the get/set native notation in mind. I hadn't realized it worked on IE, I thought it was only ES6. OTOH, dcl.prop() is nice in that it's a single syntax that lets you set enumerable etc. flags for each property.

uhop commented 6 years ago

No problem, I didn't see it initially too and was surprised why this.myFunc() is being called while defining a class instead of using instances. I even checked the tests to see if this case is not covered (it was).

dcl.prop() is nice, true. Another thing to consider is dcl() + options with detectProps: true. It is documented in http://www.dcljs.org/2.x/docs/dcl_js/dcl/ and there is an example on how it works. It may be less explicit as with dcl.prop(), yet it requires less code noise.

wkeese commented 6 years ago

I guess this is an advantage of the new ES6 (and dcl6) super() syntax, less chances for "typos" like this. I'll keep detectProps in mind. Already used enumerable: false in the options parameter and it worked quite nicely.