Home > Enterprise >  How to auto-populate an abstract property?
How to auto-populate an abstract property?

Time:04-27

I have an existing abstract class, say Vehicle and I want to create an intermediate class to reduce repetition of abstract properties in my instantiatable classes.

The problem:

abstract class Vehicle {
  abstract wheelCount: number
  abstract tireCount: number
}

class Car extends Vehicle {
  wheelCount = 4
  tireCount = 4 // Tire count is the same as wheel count
}

class Truck extends Vehicle {
  wheelCount = 4
  tireCount = 4 // Tire count is the same here too
}

class Bike extends Vehicle {
  wheelCount = 2
  tireCount = 2 // Tire count is the same - I really need to abstract this
}

An invalid solution:

abstract class Vehicle {
  abstract wheelCount: number
  abstract tireCount: number
}

// I want an intermediate class like this
abstract class StandardVehicle extends Vehicle {
  tireCount = wheelCount
}

class Car extends StandardVehicle {
  wheelCount = 4
}

class Truck extends StandardVehicle {
  wheelCount = 4
}

class Bike extends StandardVehicle {
  wheelCount = 2
}

What are the valid solutions to this please?

Please note, there are cases where wheelCount and tireCount will differ so I can't combine these properties in Vehicle.

CodePudding user response:

It is possible to implement properties with getter and setter and then just assign their values in constructor.

So code would like this:

abstract class Vehicle {
  abstract wheelCount: number
  abstract tireCount: number
}

and class with properties and corresponding getters and setters:

abstract class StandardVehicle extends Vehicle {
    private _wheelCount!: number;
    get wheelCount(): number {
        return this._wheelCount;
    }
    set wheelCount(value: number) {
        this._wheelCount = value;
    }


    private _tireCount!: number;
    get tireCount(): number {
        return this._tireCount;
    }
    set tireCount(value: number) {
        this._tireCount = value;
    }

    constructor(wheelCount: number) {
        super()
        this._wheelCount = this._tireCount = wheelCount
    }
}

and it is possible to assign some common value in concrete class:

class Teasl extends StandardVehicle {
    constructor(value: number) {
        super(value)
    }
}

and you can call your class like this:

const anExampleVariable = new Teasl(88)

As an alternative, the initialization function can be created to populate with values.

So the code would look like this. Abstractions:

abstract class Vehicle {
  abstract wheelCount: number
  abstract tireCount: number
}

abstract class StandardVehicle extends Vehicle {
  constructor(value:number) {
      super()
      this.init(value)
  }

    private init(value:number) {
        this.wheelCount = this.tireCount = value
    }
}

and concrete implementations:

class Foo extends StandardVehicle {
    wheelCount!: number
    tireCount!: number

    constructor(value: number) {
        super(value)
    }
}

and usage:

const anExampleVariable = new Foo(88)
console.log(anExampleVariable)
  • Related