user1031947
user1031947

Reputation: 6664

In ES6, how to override a private method in a super class?

I'm learning about classes in ES6...

I'd like to use private properties, in some form, so that only certain methods can be called from an instance of a class.

For example using Symbol...

/* A.js */

const _privateMethod = Symbol('_privateMethod')
class A {
    [_privateMethod]() {
        return 'yup'
    }
    do() {
        return this[_privateMethod]()
    }
}

const a = new A()
a.do() /* yup */

..._privateMethod cannot be called directly. So far so good.

However, I am wondering how to then go about overriding _privateMethod in a class that inherits from A. For example, the following will not work:

/* B.js */

const _privateMethod = Symbol('_privateMethod')
class B extends A {
    [_privateMethod]() {
        return 'nope'
    }
}

const b = new B()
b.do() /* yup */

How is it recommended to do this?

Upvotes: 5

Views: 3234

Answers (4)

Estus Flask
Estus Flask

Reputation: 222369

The reason why programming concepts are used in practice is because they provide some benefits to a developer, this includes encapsulation, too. If it provides more disadvantages than benefits, this means that it shouldn't be applied, or the way it was applied was wrong.

JavaScript doesn't have provide encapsulation as language feature. Symbol is an acceptable way to implement it, but it has its specificity that can make it unsuitable for the task.

A symbol that serves as an identifier for private (protected) member should always be exported together with a class it belongs to:

export const _privateMethod = Symbol('_privateMethod');
export class A {
    [_privateMethod]() {/*...*/}
    /*...*/
}

...

import { _privateMethod, A } from './a';

class B extends A {
    [_privateMethod]() {/*...*/}
}

If this is not possible or practical, this means that a symbol is inappropriate choice for encapsulation, because it provides disadvantages without any real benefits.

Since information hiding doesn't serve security purposes in JavaScript (symbols are accessible with Object.getOwnPropertySymbols), the alternative to encapsulation mechanism is the use of Hungarian notation and/or JSDoc annotations. They provide a developer with necessary information about public interface:

export class A {
    /** @protected */
    _privateMethod() {/*...*/}
    /*...*/
}

Upvotes: 2

LPZadkiel
LPZadkiel

Reputation: 571

you already has the right answer, check this

const _privateMethod = Symbol('_privateMethod')
class A {
    [_privateMethod]() {
        return 'yup'
    }
    do() {
        return this[_privateMethod]()
    }
}

const a = new A()
document.write(a.do()+ "<br><br>" )

class B extends A {
    [_privateMethod]() {
        return 'nope'
    }
}

const b = new B()
document.write(b.do()+ "<br><br>")

Upvotes: 0

Michał Perłakowski
Michał Perłakowski

Reputation: 92501

You can use the Object.getOwnPropertySymbols() function:

const A = (function() {
  const _privateMethod = Symbol('_privateMethod')
  return class A {
      [_privateMethod]() {
          return 'yup'
      }
      do() {
          return this[_privateMethod]()
      }
  }
}());

(function() {
  const _privateMethod = Object.getOwnPropertySymbols(A.prototype)
    .find(x => x.toString() === 'Symbol(_privateMethod)')
  class B extends A {
      [_privateMethod]() {
          return 'nope'
      }
  }
  
  const b = new B()
  console.log(b.do());
}());

Upvotes: 0

Bergi
Bergi

Reputation: 664385

Calling Symbol('_privateMethod') again creates a new, distinct symbol (even if it has the same description). You are creating a different method with a different key, not overwriting the original one.

You will need to use the exact same symbol to define the method in the subclass. You can either get it from Object.getOwnPropertySymbols(A.prototype) or by exporting the _privatMethod symbol as a constant from A.js and importing it in B.js (together with the class A). However, if you want to make the class extensible, I would recommend to simply not use symbols at all.

Upvotes: 3

Related Questions