Dart: Abstract Classes & Implicit Interfaces
An abstract class is a blueprint that other classes must follow, but it can't be instantiated itself. Dart also lets any class act as an 'implicit interface,' forcing other classes to implement its public API without inheritance.
WHY IT EXISTS: To enforce a common structure across related classes without allowing the creation of a generic, incomplete base object. Abstract classes provide a way to define a contract and share code, while implicit interfaces allow for API contracts without forcing an inheritance relationship.
THE MENTAL MODEL: Think of an abstract class as a partially completed house blueprint. It defines required rooms (abstract methods) and might have pre-designed plumbing (concrete methods), but you can't live in the blueprint itself. You must create a concrete house that finishes all the rooms. An implicit interface is different. It's like taking a finished car and telling a factory, "Build a new car with the exact same public controls, but you design the engine and chassis yourself." You're only copying the public API, not the implementation.
HOW IT WORKS: An abstract class is declared with the abstract keyword. It can contain abstract methods (signatures without a body) and concrete methods (with a body). Subclasses use extends and must implement all inherited abstract methods. You cannot create an instance of an abstract class. An implicit interface is created from any regular class. Another class uses the implements keyword, which forces it to provide its own implementation for every public member of the "interface" class. No code is inherited.
WHEN TO USE IT: Use an abstract class to share implementation among several closely related classes. For example, an abstract Shape class could have a concrete color property and an abstract calculateArea() method for Circle and Square to implement. Use an implicit interface when you want a class to conform to an API contract without sharing implementation or forcing an inheritance hierarchy, like defining a Logger contract for different logger types.
WHEN NOT TO USE IT: Don't use an abstract class if you only need to define a contract with no shared code; a regular class used as an interface is better. The biggest footgun is using implements when you want to inherit behavior and code from a superclass. For that, you must use extends. implements provides zero implementation from the interface.
ONE CANONICAL EXAMPLE: An abstract class Animal could define a concrete breathe() method that all animals share, and an abstract makeSound() method. A Dog class would then extend Animal and only need to provide its own implementation for makeSound(). For an implicit interface, you could have a regular class Speaker with an announce() method. A different class, SmartSpeaker, could implement Speaker, which forces it to provide its own version of the announce() method, guaranteeing it has the same API but without inheriting any code from Speaker.
Read the original → dart.dev
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.