-2

This is example of very basic code:

"use strict";

class aClass {
    readFromA() {
        console.log(this.a);
    }


    constructor() {
        this.a = 5;
    }
}

class bClass extends aClass {
    readFromB() {
        console.log(this.a);
    }


    constructor() {
        super();
        this.a = 10;
    }
}

let bc = new bClass();
bc.readFromA(); //10
bc.readFromB(); //10

My intention is to involve the most modern techniques of object programming in JS. ES6 introduces classes and inheritance of them. It seems to be useless programming style yet. For example, code above overrides property "a" in class aClass by the same variable name in bClass. . Lets assume that 2 proggramers create those classes. Each of them doesn't know what variable names will be used. If they both use the same variable name - it will couse a catastrophy! Both classes will read and write the same property making application crash. How to protect properties in classes against overriding and be able to utilize "extends" functionality?

Pointy
  • 405,095
  • 59
  • 585
  • 614
Marek
  • 9
  • 4
    That is exactly how it is supposed to work. – some Jan 22 '18 at 00:43
  • 1
    In both methods, the value of `this` is the `bc` object, because it was from `bc` that you invoked them both. –  Jan 22 '18 at 00:43
  • 1
    Why is it that you would expect anything different to happen? – Pointy Jan 22 '18 at 00:43
  • *"...Each of them doesn't know what variable names will be used."* They should know before inheriting from another class. –  Jan 22 '18 at 00:44
  • I agree that this is supposed to work this way but this is also huge limitation and must be workaround somehow. For example in other languages such a C++, there are private members. Each class give access to some public and protected methods and properties. Rest of them are hidden and impossible to override. For example if class A can read the file from disk, I expect to get content of this file in class B. I don't need access to the file handler etc. Moreover if I have acces to the file handler in class B, I can destroy functionality of base class A by not intended overriding this variable. – Marek Jan 22 '18 at 11:09

2 Answers2

2

Each of them doesn't know what variable names will be used. If they both use the same variable name - it will cause a catastrophy!

This is of course a very bad practice. You should not inherit from classes that you don't know, and every class should document its public members for exactly this purpose.

How to protect properties in classes against overriding and be able to utilize "extends" functionality?

Don't use the same keys. If you cannot ensure this using proper documentation or naming conventions, symbols were made to solve exactly this problem.

const a = Symbol("a");
export default class {
    constructor() {
        this[a] = 5;
    }
    readFromA() {
        console.log(this[a]);
    }
}

import ClassA from '…';

const a = Symbol("a"); // a different symbol than that in the AClass module
class BClass extends AClass {
    constructor() {
        super();
        this.a = 10;
        this[a] = 15;
    }
    readFromB() {
        console.log(this.a, this[a]);
    }
}

const x = new BClass();
x.readFromA(); // 5
x.readFromB(); // 10, 15
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Do you suggest to keep all classes in separate modules? If 2 files will have the same symbol (const a) then they will be treated as different symbols? I can see Firefox and Internet Explorer don't suport this functionality by CanIUse. – Marek Jan 22 '18 at 12:35
  • Well I just assumed if the two programmers did not know about the other classes internals, they surely would reside in different modules. If they don't, you also have to care about avoiding variable name collisions (`const a`)! :-P – Bergi Jan 22 '18 at 13:32
  • No, the symbols are distinct because there are two calls to `Symbol`, not because they reside in different modules. Symbols are supported by both Firefox and Edge. – Bergi Jan 22 '18 at 13:33
  • I said "2 programers" in order to illustrate that 2 classes can be developed independly and the same variable names can appear in both causing conflict. Not necessarily I meant 2 separate files :-) I got errors tryink import modules in Edge, Chrome and Firefox. It seems that modularization will be possible in the future :-( Is it possible to create module-like classes in one file? I mean keeping unique variable names for both classes. – Marek Jan 22 '18 at 15:22
  • You can use any module bundler or module system that you want, it doesn't need to be ES6 modules. You can as well just place them in the same file. – Bergi Jan 22 '18 at 20:57
0

In the meantime I found solution to mentioned problem of private properties in classes. Bergi's idea was implemented. Here is the code:

"use strict";


let aClass = (function () {
let a = Symbol("a");

class aClass {
    readFromA() {
        console.log(this[a], this.b);
    }

    constructor() {
        this[a] = "aaa"; //this is private
        this.b="bbb"; // this is public
    }

}

return aClass;
})();

let bClass = (function () {
let a = Symbol("a");

class bClass extends aClass {
    readFromB() {
        console.log(this[a], this.b);
    }

    constructor() {
        super();
        this[a] = "ccc"; //this is private
        this.b="ddd"; // this is public
    }

}

return bClass;
})();

let bc=new bClass();
bc.readFromA();
bc.readFromB();

The result is: aaa ddd ccc ddd

Thanks to encapsulation I managed with using the same property name "a" in both classes which receives different values for each of them. Property "b" is public and can be overriden. With this approach, we do not have to be careful using property names in both classes. There is no risk of accidentally overwriting the non public properties of the base class. Moreover, this kind of encapsulation allows to use inheritance of classes in traditional way: by "extends" keyword.

Marek
  • 9