Is there a clean way to simulate abstract classes so that, for example, creating instances like var cat = new Animal('cat')
and var dog = new Animal('dog')
lets you call cat.say()
and dog.say()
to output meow and bark respectively?
What’s the most elegant approach to achieve this behavior?
JavaScript doesn’t have built-in abstract classes like some other languages, but you can simulate them pretty neatly using ES6 classes.
One common pattern is to throw an error if someone tries to instantiate the base class directly so your Animal class constructor checks if new.target === Animal
and throws if so.
Then, subclasses like Cat and Dog extend Animal and implement their own say() method. This keeps things clean and makes sure the base class can’t be instantiated alone.
Another cool way is to define your base Animal class with methods that throw errors if not overridden.
For example, say() can just throw new Error(“You must override say()”). Then subclasses like Cat and Dog implement their own say() functions that return “meow” or “bark”.
This way, even if someone forgets to override, you get a clear error at runtime.
If you want to keep things simple and more dynamic, you could use a factory function that returns different objects based on the type you pass in.
So instead of using new Animal()
, you have a function like createAnimal(type)
which returns an object with the right say()
method. It’s not a class per se, but it’s pretty elegant and easy to maintain, especially if you don’t want to fuss with inheritance.