Nejdi Kroi
Nejdi Kroi

Reputation: 612

Adding an instance of subtype of abstract class in typescript

I was wondering how would one implement the example below. I am trying to abstract away some core functionality of House. I ran into this situation.

Let's say there is an abstract Animal class extended as shown below

abstract class Animal{
    constructor(age:number){
        this.age = age;
    }
    age:number;
}
class Dog extends Animal{
    constructor(age:number){
        super(age);
    }
    bark(){
        console.log("Bark");
    }
}

class Cat extends Animal{
    constructor(age:number){
        super(age);
    }
    meow(){
        console.log("Meow");
    }
}

The whole point is to make this a base class of the application and many classes of different animal houses extend this and its core functions

abstract class House{
    animals:Animal[];

    addAnimal(humanAge:number){
        const animalAge = humanAge/7;
        // How to add an animal here kind of like animals.push(new Animal(animalAge));
    }
}

class DogHouse extends House{
    doSomethingElseHERE(){
       console.log("Something else")
    }
}

new DogHouse().addAnimal(23); //What would be a viable solution to make this work seamlessly in every animal house like this

So what would be a good implementation for add function in the abstract class House

Upvotes: 1

Views: 656

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249756

You can make House generic so instead of Animal the element type can be any type of animal in derived classes. Also if you need to create an element in the base class you can pass in the constructor of the specific animal as a parameter to the base class:

abstract class House<T extends Animal>{
    animals: T[];
    constructor(private elementCtor: new (age: number) => T) {

    }

    addAnimal(humanAge: number) {
        const animalAge = humanAge / 7;
        this.animals.push(new this.elementCtor(animalAge));
    }
}

class DogHouse extends House<Dog> {
    constructor() {
        super(Dog)
    }
    doSomethingElseHERE() {
        console.log("Something else")
    }
}

Another option is to create an abstract method in House:

abstract class House{
    animals: Animal[];
    constructor() {

    }
    abstract createAnimal(age: number): Animal
    addAnimal(humanAge: number) {
        const animalAge = humanAge / 7;
        this.animals.push(this.createAnimal(animalAge));
    }
}

class DogHouse extends House {
    createAnimal(age: number): Animal {
        return new Dog(age);
    }
    constructor() {
        super()
    }
    doSomethingElseHERE() {
        console.log("Something else")
    }
}

Upvotes: 2

Related Questions