0

I have the following Code:

class Base {
 static id = 5;
 static arr = [];
}

class A extends Base {}
class B extends Base {}

This gives every sub-class its own static id property:

A.id++;

console.log(A.id) : 6  (Only this one got increased)
console.log(B.id) : 5
console.log(Base.id) : 5

However this is not the case for Objects. When the Subclass gets created, a reference to Base-Class's Object is passed, instead of (in the case of Primitives) a simple copy. This gives the following result:

A.arr.push('a');

console.log(A.arr) : ['a']
console.log(B.arr) : ['a']     (I want this to stay empty)
console.log(Base.arr) : ['a']  (I want this to stay empty)

How would I have to change static arr = []; so that each sub-class gets its own static array?

11
  • Just put static arr = []; in class A and class B as well. Commented Aug 15, 2021 at 19:04
  • 1
    What are you using arr and id for? This smells like a design issue. What do your subclasses represent? Commented Aug 15, 2021 at 19:04
  • 2
    "I want to have a List of Running Instances" - well, you shouldn't store these in static properties of the respective class. What if you want to have a separate list of "running" instances for some other purpose (testing, representing remote games, etc)? Store these in your application, not on your class; that way you can create multiple applications from the same code. Commented Aug 15, 2021 at 19:18
  • 1
    Also notice that Game.arr should contain all running Game instances, no matter what subclass they have. If you want a separate list that contains only TicTacToe games, make a separate list. It's not the responsibility of the Game class to do that. Commented Aug 15, 2021 at 19:19
  • 1
    And last but not least, reconsider whether an inheritance hierarchy Game -> TwoPlayerRoundBasedGame -> TicTacToe is really the best design. Maybe they should be mere interfaces? Maybe they should be mixins? Maybe you should use composition instead? Commented Aug 15, 2021 at 19:20

1 Answer 1

1

A.arr is as distinct from B.arr as A.id is from B.id. The issue is that A.id++ is equivalent to A.id = A.id + 1, which replaces the value of A.id with a new value. A.arr.push('a') does not replace the contents of A.arr, which is a reference to the same object in B.arr.

This has nothing to do with classes or static members. Observe:

let a = [];
let b = a;
a.push(1);
console.log('a refers to the same object as b; change that object, both a and b change');
console.log(`a=${a}; b=${b}`);
b = [...a, 2];
console.log('b refers to a different object from a');
console.log(`a=${a}; b=${b}`);

I assume you are asking how to assign a new object to every subclass. Since AFAIK JavaScript doesn't have subclass hooks, I believe the only way would be to do it manually for each subclass.

class Base {
  static arr = [];
}

class A extends Base {
  static arr = [];
}
class B extends Base {
  static arr = [];
}

A.arr.push(1);
B.arr.push(2);
console.log(`A.arr=${A.arr}; B.arr=${B.arr}`);

Another approach is to use a static getter to do it for you. For example, this might work:

class Base {
  static _arr = null;
  static get arr() {
    return (this._arr ??= []);
  }
}

class A extends Base {}
class B extends Base {}

A.arr.push(1);
A.arr.push('a');
B.arr.push(2);
B.arr.push('b');
console.log(`A.arr=${A.arr}; B.arr=${B.arr}`);

Sign up to request clarification or add additional context in comments.

3 Comments

A.arr is as distinct from B.arr — A.arr === B.arr; they’re identical. Saying that they’re distinct is misleading.
@SebastianSimon It's "as distinct as", a comparison. Notice that also A.id === B.id. Yes, they're identical.
Thank you! I also had the idea of using static getters, but static get arr() {return []}; didn't work. But yours works perfectly, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.