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)