programmingnoob
programmingnoob

Reputation: 1

How to correctly implement a 'Child' class that extends a 'Parent' class and inherits a class field from the latter?

This is my task

I have tried adding into the creating a new function here but it's not working. Not sure if i'm creating the function correctly. Could anyone help to see?

class Parent {
    abilities = []

    constructor(){
        this.abilities.push("Parenting");
        this.abilities.push("Role modeling");
    }

    showAbilities(){
        console.log("These are the abilities:")
        for(const a of this.abilities){
            console.log(a);
        }
    }
}

const p = new Parent();
p.showAbilities(); // Observe that this function prints "Parenting" and "Role modeling".

// Task 1: Add code here
class Child extends Parent {
    addNewAbility = []

    super() {
        this.addNewAbility.push("Parenting");
    }
}

const c = new Child();
c.addNewAbility("Dancing");
c.showAbilities(); // This function should print "Parenting", "Role modeling" and "Dancing".

Upvotes: -2

Views: 103

Answers (2)

Peter Seliger
Peter Seliger

Reputation: 13432

I've read all points of the task, given to the OP, quite carefully.

In addition to agreeing about the poor quality of the provided course material, I noticed the hash-prefix / # of the #abilities array.

After point one and two ...

  • Implement a Child class that extends the Parent.
  • Add a constructor to the Child class [...that can call...] super().

... point three does target the Child class implementation ...

  • Implement a new function addNewAbilities([...]) in the Child class where the new ability will be added to the Parent's #abilities array.

Even though this exact formulation unveils a lack of understanding what kind of language features are relevant for useful real world implementations, the task can be solved.

In case #abilities gets interpreted correctly as private class property, the most important general principle to know is, that ...

  • private class properties can not be inherited.

But one can emulate such a behavior as the next following and thoroughly commented example code is going to prove ...

class Parent {
  /*
   *  ... private property ...
   *
   *  - note the hash prefix
   *    as of the given task ...
   *
   *    "... where the new ability will be
   *     added to the Parent's #abilities array"
   */
  #abilities = [];

  constructor(){
    this.#abilities.push('Parenting', 'Role modeling');
  }
  get abilities () {
    // - with a getter one never ever does
    //   directly expose the protected value.

    return [...this.#abilities]; 
  }
}

class Child extends Parent {
  /*
   *  I m p o r t a n t:
   *
   *  - private class properties can not be inherited.
   *
   *  - thus one has to   e m u l a t e
   *    what the given task does ask for ...
   *
   *    "Implement a new function addNewAbilities [...]
   *     in the Child class where the new ability will
   *     be added to the Parent's #abilities array."
   */
  #abilities = [];

  constructor() {
    super();

    // - N o t e:
    //
    //   Both getter calls do access the same reference as long as
    //   `Child` does not implemented its own `abilities` getter.

    console.log('Child::new ... this.abilities ...', this.abilities);
    console.log('Child::new ... super.abilities ...', super.abilities);
  }

  // shadowing the super getter.

  get abilities () {
    // - return a concatenated array of just
    //   unique super and child ability values.

    return [
      ...new Set(
        super.abilities.concat(this.#abilities)
      )
    ];
  }

  addAbilities(...args) {
    // - make sure a child's `abilities`
    //   contains unique values only.

    this.#abilities = [
      ...new Set(
        this.#abilities.concat(args.flat())
      )
    ];
    // - use the child's `abilities` getter in order
    //   to return the correct overall abilities size.

    return this.abilities.length;
  }
}
const parent = new Parent;
const child = new Child;

console.log('parent.abilities ...', parent.abilities);
console.log('child.abilities ...', child.abilities);

console.log('child.addAbilities(...) ...',
  child.addAbilities(
    'Rules challenger', 'Wellspring of Joy',
    'Parenting', 'Role modeling',
    'Rules challenger', 'Wellspring of Joy',
  )
);
// ... same ...

/*console.log('child.addAbilities(...) ...',

  // single array instead of mutiple parameters.
  
  child.addAbilities([
    'Rules challenger', 'Wellspring of Joy',
    'Parenting', 'Role modeling',
    'Rules challenger', 'Wellspring of Joy',
  ])
);*/
console.log('parent.abilities ...', parent.abilities);
console.log('child.abilities ...', child.abilities);
.as-console-wrapper { min-height: 100%!important; top: 0; }

Edit ... at the OP ...

  • Please read about the purpose and the usage of the super keyword.

And in case of normal class fields (which are public) the above example code boils down to something as short as the following provided code ...

class Parent {
  constructor() {
    this.abilities = ['Parenting', 'Role modeling'];
  }
  logAbilities() {
    console.log(
      `The ${ this.constructor.name } instance has following abilities ... ${ this.abilities.join(', ') }`
    );
  }
}

class Child extends Parent {
  constructor() {

    super();

    console.log('Child::new ... this.abilities ...', this.abilities);
  }

  addAbilities(...args) {
    // - make sure a child's `abilities`
    //   contains unique values only.

    this.abilities = [
      ...new Set(
        this.abilities.concat(args.flat())
      )
    ];
    return this.abilities.length;
  }
}
const parent = new Parent;
const child = new Child;

console.log('parent.abilities ...', parent.abilities);
console.log('child.abilities ...', child.abilities);

console.log('child.addAbilities(...) ...',
  child.addAbilities(
    'Rules challenger', 'Wellspring of Joy',
    'Parenting', 'Role modeling',
    'Rules challenger', 'Wellspring of Joy',
  )
);
// ... same ...

/*console.log('child.addAbilities(...) ...',

  // single array instead of mutiple parameters.
  
  child.addAbilities([
    'Rules challenger', 'Wellspring of Joy',
    'Parenting', 'Role modeling',
    'Rules challenger', 'Wellspring of Joy',
  ])
);*/
console.log('parent.abilities ...', parent.abilities);
console.log('child.abilities ...', child.abilities);

console.log('\nparent.logAbilities() ...\n\n');
parent.logAbilities();

console.log('\nchild.logAbilities() ...\n\n');
child.logAbilities();
.as-console-wrapper { min-height: 100%!important; top: 0; }

Upvotes: 0

praizjosh
praizjosh

Reputation: 142

In the Child class, you don't need to define 'addNewAbility' as an array. Instead, you should use the abilities property inherited from the Parent class to store more abilities.

Also, your Child class is missing the constructor function. The constructor should use the super() keyword to call the constructor of the parent class Parent.

Here your revised code:

class Child extends Parent {
    constructor() {
        super(); 
        this.abilities.push("Childcare"); 
    }
}

Cheers!

Upvotes: -1

Related Questions