JavaScript - Accessing a child variable in a parent class - javascript

In JavasScript, is it possible to define a variable in a child class, then access it in a parent class? I imagine the child class would look something like this:
export default class ChildClass extends ParentClass {
constructor() {
this.path = 'register';
}
}
A use-case scenario is an HTTP service class as the parent that contains general, reusable methods and a child class that defines the exact route that will be accessed. Assuming it's possible, how could I then access this.path in the parent class?

You don't need to do anything special, it just works.
As mentioned in the comments, it doesn't necessarily make sense to design your classes like this, since the actual class of the object might not be that child class.
class ParentClass {
printPath() {
console.log(this.path);
}
}
class ChildClass extends ParentClass {
constructor() {
super();
this.path = 'register';
}
}
var c = new ChildClass();
c.printPath();
var p = new ParentClass();
p.printPath();

Related

Typescript call method from child class returns incorrect type

Having two classes. Parent class implements all methods, child class only supplements or overrides those it needs.
class Parent<M extends typeof BaseModel> {
model: M
getList(){
return this.model.queryList()
}
}
class Child extends Parent<typeof MyModel>{
model: typeof MyModel
constructor(){
super();
this.model = MyModel;
}
}
const childProvider = new Child();
childProvider.getList() // returns BaseModel.queryList() result instead of MyModel.queryList() result
Any idea how I can improve this so I don't need to overwrite every single method from the parent class but when using parent methods, they should be casting proper types.

Is there a more direct way to achieve this in Javascript?

I have an inheritance like this:
class Parent {
some_object_property = ["some_object_property_depending_on_initialization"];
constructor() {...}
}
class Child extends Parent {
some_object_property = [...super.some_object_property, 'child_property']
}
Is there a way to let the Child inherit and extend object property some_object_property from the Parent?
I know I can achieve the end result through getter and setter. Is there a more direct way?
Did you mean this?
class Parent {
constructor() {
this.someProp = ['someprop test', 'something else'];
}
}
class Child extends Parent {
constructor() {
super();
this.someProp = [...this.someProp ,'added child prop'];
}
}
let myChild = new Child();
console.log(myChild.someProp);
It produces an error saying "super is not an identifier recognizable".
Yes, you cannot use super in a class field initialiser. Either put that line inside the constructor where it belongs (like in #DannyEbbers' answer), or just use the this keyword instead - it's just as good, no need to use super here:
class Parent {
some_object_property = ["some_object_property_depending_on_initialization"];
}
class Child extends Parent {
some_object_property = [...this.some_object_property, 'child_property']
}
this.some_object_property will refer to the instance property that was initialised by the parent constructor before you're overwriting it with a new value - it runs as if written inside the constructor.

Javascript Child Class method not overriding Parent Class Method

I am trying to override one method from the parent class, but there are some issues.
Below is the code snippet of my scenario which I am trying.
class Parent {
add = () => {
console.log('Parent method');
}
}
class Child extends Parent {
add () {
console.log('Child Method');
}
}
// Creating an instance
const child = new Child();
child.add();
It is calling the Parent method add as that is arrow function, Can someone explain why this is happening. If I make the parent function a simple javascript method then child is able to override.
Additonal Details :
I don't have access to Parent as it is part of library.
I can't make my child class method as instance properties (arrow function)
, the reason for being that there are further
specification written for child (child of child) and If we use arrow
functions we will not be able to call the super.
Child function name can't be renamed.
This is one of few reasons why arrow methods aren't convenient. They limit the ways in which a class can be extended and tested.
Class fields (which arrow methods are) are syntactic sugar for constructor code:
class Parent {
constructor() {
this.add = () => {...};
}
}
Only another arrow method can override parent arrow method, because they are defined in class constructor, not on class prototype:
class Child extends Parent {
add = () => {
/* no super.add here because add is not prototype method */
}
}
If super.add is intended to be used, a workaround is to store parent method:
class Child extends Parent {
superAdd = this.add;
add = () => {
this.superAdd();
}
}
Notice that since this is syntactic sugar for constructor code, the order in which superAdd and add are defined matters.
The parent add is an instance property, and it overshadows the child's class method, which is part of the instance's prototype. It's a bit hacking, but you can rename and delete the class property in the constructor:
class Parent {
add = () => {
console.log('Parent method');
}
}
class Child extends Parent {
constructor() {
super();
this.parentAdd = this.add;
delete this.add;
}
add() {
console.log('Child Method');
this.parentAdd(); // if you need call the parent's method
}
}
const child = new Child();
child.add();

Javascript classes : how to access overridden parent class functions in parent class code

Javascript ES6 ( node 8.4.0 and latest chrome and recent Firefox )
I expected
class Parent {
init(){
console.log("Parent init") ;
this._surname = "McClass" ;
}
constructor() {
console.log("Parent constructor") ;
this.init();
}
get surname(){
return this._surname ;
}
}
class Child extends Parent {
init(){
console.log("Child init") ;
}
constructor() {
super();
console.log("Child constructor") ;
this.init();
}
}
var child = new Child() ;
console.log(child.surname);
to give the following output;
Parent constructor
Parent init
Child constructor
Child init
McClass
(which is what comparable C++ code gives)
Alas, I got this ;
Parent constructor
Child init
Child constructor
Child init
undefined
Am I doing something wrong or is this the correct intended behaviour and if so how is it justified ?
EDIT;
See MinusFour's answer below on how to achieve what I was trying to do / expecting.
As to why the observed output is the "correct" behaviour and justified ;
As Bergi pointed out (in comments) all calls to object methods in js are effectively "virtual" (the last method of that name added to the object's prototype inheritance chain being the first found and hence executed). It turns out calls are still effectively virtual in a class construction context.
C++ does not apply virtual method behaviour during construction but then again Java does and you get the same output (as above) in comparable Java code so there is a precedent for the observed behaviour.
You could do:
Parent.prototype.init.call(this);
class Parent {
init() {
console.log("Parent init");
this._surname = "McClass";
}
constructor() {
console.log("Parent constructor");
Parent.prototype.init.call(this);
}
get surname() {
return this._surname;
}
}
class Child extends Parent {
init() {
console.log("Child init");
}
constructor() {
super();
console.log("Child constructor");
this.init();
}
}
var child = new Child();
To make sure it never gets overridden, but I would suggest you just not override it in the first place.
It is expected behaviour, just because it can be seen in established ES6 class implementations that follow the specs.
this refers to current class instance, which is an instance of Child in the case when Child is instantiated - even in Parent class, because there is only one instance, and it is instanceof Child.
If Child overrides the method, it's its responsibility to provide mechanism to call it. Considering that init follows some documented convention and is the place where class initialization happens in order to make constructor leaner and more testable, it is:
class Parent {
init(){...}
constructor() {
this.init();
}
...
}
...
class Child extends Parent {
init(){
super.init();
...
}
// optional, as long as `init` contains all init logic
constructor() {
super();
}
}
Which results in a sequence:
Parent constructor
Parent init
Child init
Child constructor
If init is supposed to work totally independently in both classes, it shouldn't be overridden. Methods should be named differently, like initParent and initChild. Or any other way to avoid naming collisions can be used, e.g.:
const init = Symbol('Parent init');
class Parent {
[init](){...}
constructor() {
this[init]();
}
...
}
...
const init = Symbol('Child init');
class Child extends Parent {
[init](){...}
constructor() {
this[init](); // totally independent method
}
}

Access child constructor from base class constructor

Given the following class hierarchy: ChildClass extends ParentClass, is it possible to access the ChildClass constructor function from the ParentClass constructor? For example:
class ChildClass extends ParentClass
{
constructor()
{
super()
}
}
ChildClass.prop = 'prop'
class ParentClass
{
constructor()
{
if (this._child().prop == 'prop') // here
{
console.log("All ok");
}
}
get _child()
{
return this.constructor;
}
}
In other words, what I'm trying to do is access the child's 'static' property for verification purposes
is it possible to access the ChildClass constructor function from the ParentClass constructor?
Every Child is a Parent but not every Parent is a Child.
No. You can't. Even if possible with some dirty codes, don't do it. Rethink about your design. In the chain of Inheritance every Child should inherit the properties of Parent. Not the reverse.
Just think that there are 3 children and which children's props you get ? Bummer.
It should be this._child instead of this._child(), because child is property accessor, not a method:
class ParentClass
{
constructor()
{
if (this._child.prop == 'prop')
{
console.log("All ok");
}
}
get _child()
{
return this.constructor;
}
}
_child getter is redundant and misleading. Usually this.constructor is used directly:
class ParentClass
{
constructor()
{
if (this.constructor.prop == 'prop')
{
console.log("All ok");
}
}
}
Referring to 'child' in parent class is semantically incorrect (a parent doesn't and shouldn't 'know' about its children, and _child can be a parent itself), but referring to this is not.

Categories

Resources