Implements vs extends: When to use? What's the difference?
When you want to create a specialized version
of an existing class, extends
is the keyword to use, while for adhering to a contract
of specific behaviors, you'd go for implements
.
extends
: Develop a subclass enriched with new or modified actions.implements
: Ensure your class meet the obligations defined by an interface.
Example:
By using implements Drivable
, Vehicle
commits to have a drive
method, and ElectricCar
not only inherits but can enhance that method from Vehicle
via extends
.
Implements and Extends In-depth
The extends
keyword will become your best friend when you're intending to create a particular version or refinement of an existing class. It forms an "is a" relationship, as your new class is a subtype of the extended class. Conversely, implements
almost feels like swearing an oath that your class will accomplish some tasks, instigating a form of "has a" capability.
Knowing when to inherit
Hereβs when inheritance can come into play:
- Reuse code: Share functionalities between class hierarchies.
- Polymorphism: A subclass object can be treated as a parent class object.
- Add new behaviors to the subclass without disrupting its parent.
Implementing interfaces intelligently
Often interfaces depict the services or capabilities ventured by a class, like Serializable
, Cloneable
, and the likes. They equip you to write adaptable and diverse code that can interact with any object promising particular behaviors.
Blending inheritance with interfaces
Sometimes you'll need to blend inheritance and interfaces. A typical case is where a class already extends a class but also needs to guarantee additional contracts by embracing interfaces.
Deciphering dynamic binding
Understanding the magic trick of dynamic binding is key for mastering extends
and implements
. The JVM ensures that the method invoked on an object matches its runtime type rather than its compile-time type.
Unleashing polymorphism's potential
- Override to dish out custom behavior.
- Write generic and flexible code.
- Translate objects into instances of their parent class.
@Override: Optional, but essential
Even though optional, it's highly recommended to use @Override
as it clarifies intentions, helps you steer clear of bugs, and ensures that a method is truly overriding a superclass method or implementing one from an interface.
Harnessing the power of 'default' methods
Java 8 introduced default
methods allowing you to provision default implementation for some methods. Super useful when you need to extend interfaces without jeopardizing existing implementations:
Classes may opt to implement Swimmable
without specifically defining swim()
, yet they are free to override it if needed.
Overcoming the limitation of single inheritance
Java does not support multiple inheritances due to the diamond problem. If multiple ancestors have different implementations for the same methods, then which one should the descendant class inherit? A surefire headache, right? Thus, classes can implement multiple interfaces, providing the benefits of multiple-heritage without the complications!
An interface isn't just a contract
Interfaces in Java also serve as data types. When you declare a variable of an interface type, it can reference any object that implements the interface.
Practical use-cases
- Frameworks like the popular Spring heavily rely on interfaces for dependency injection.
- Classic design patterns like Strategy, Observer, or Decorator, utilize interfaces to scaffold families of algorithms, craft publish/subscribe mechanisms, or assign responsibilities to objects respectively.
- Interfaces maintain their quintessential status in API development, ensuring a steady contract across different implementations.
Was this article helpful?