TheSmartMonkey
TheSmartMonkey

Reputation: 1040

How to use a callback function in a class with inheritance

How can I use a method from the parent in a child method that is used as a callback function

class Parent {
    numbers: number[];

    constructor(numbers: number[]) {
        this.numbers = numbers;
    }

    protected iterateNumbers(iterCallback: (nb: number) => void): void {
        for (const nb of this.numbers) {
            iterCallback(nb);
        }
    }

    protected inc(nb: number): number {
        return nb++;
    }
}

class Child extends Parent {
    constructor(numbers: number[]) {
        super(numbers)
    }

    getNumbers(): void {
        this.iterateNumbers(this.displayNumber);
    }

    private displayNumber(nb: number): void {
        console.log(this.inc(nb));
    }
}

const c = new Child([1, 2, 3, 4, 5]);
c.getNumbers();

This code results in this error : TypeError: Cannot read property 'inc' of undefined

modified with super()

Upvotes: 1

Views: 1210

Answers (2)

TheSmartMonkey
TheSmartMonkey

Reputation: 1040

Found a way to do the same thing but with a none static method

ES6 style allows you to use new features, such as super keyword. super keyword it's all about parent class context, when you are using ES6 classes syntax.

class Parent {
    numbers: number[];

    constructor(numbers: number[]) {
        this.numbers = numbers;
    }

    protected iterateNumbers(predictionCallback: (nb: number) => void): void {
        for (const nb of this.numbers) {
            predictionCallback(nb);
        }
    }

    protected inc(nb: number): number {
        return nb++;
    }
}

class Child extends Parent {

    constructor(numbers: number[]) {
        super(numbers)
    }

    getNumbers() {
        this.iterateNumbers(this.displayNumber);
    }

    private displayNumber(nb: number): void {
        console.log(super.inc(nb));
    }
}

const c = new Child([1, 2, 3, 4, 5]);
c.getNumbers();

Upvotes: 1

about14sheep
about14sheep

Reputation: 1999

You need to call the super method in the constructor of the child class in order to access properties and methods of the super class.

Also, as you have the displayNumber method private you will not be able to access it from an object created from the child class. Removing the private keyword would allow access

Try changing your extended child to include the constructor method and super call:

class Child extends Parent {

    constructor() {
        super()
    }
    
    getNumbers(): void {
        this.iterateNumbers(this.displayNumber);
    }

    displayNumber(nb: number): void {
        console.log(this.inc(nb));
    }
}

You can read more in the MDN docs on the super keyword

UPDATE:

After testing a little I have found a solution to why you are getting that error, of course it's all about context. If you make the inc method static you will be able to call it by Parent.inc()

By passing the displayNumber method in as a callback you are loosing the context of the class you are wanting to call it from. This is why you get the undefined error.

class Parent {
    numbers: number[];

    constructor(numbers: number[]) {
        this.numbers = numbers;
    }

    protected iterateNumbers(iterCallback: (nb: number) => void): void {
        for (const nb of this.numbers) {
            iterCallback(nb);
        }
    }

    static inc(nb: number): number {
        return nb++;
    }
}

class Child extends Parent {
    constructor(numbers: number[]) {
        super(numbers)
    }

    getNumbers(): void {
        this.iterateNumbers(this.displayNumber);
    }

    private displayNumber(nb: number): void {
        console.log(Parent.inc(nb));
    }
}

const c = new Child([1, 2, 3, 4, 5]);
c.getNumbers(); // prints 1 2 3 4 5

If you run this code you will see the numbers printed out.

Now by using both calling the super method in the child constructor and updating the inc method to be static, and calling it as such, I think you will get the expected results.

Upvotes: 1

Related Questions