Explain Codes LogoExplain Codes Logo

Implements vs extends: When to use? What's the difference?

java
inheritance
polymorphism
interfaces
Nikita BarsukovbyNikita BarsukovΒ·Sep 8, 2024
⚑TLDR

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:

interface Drivable { // No road, no rules... just kidding, just a contract (not clash of clans) void drive(); } class Vehicle implements Drivable { public void drive() { // Taking the road less driven... pun intended πŸ˜‰ } } class ElectricCar extends Vehicle { // Inherits the drive method, can soup it up even more! }

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:

Interface Swimmable { default void swim() { System.out.println("Just keep swimming..."); // Who sung it better? Dory or me? πŸ˜„ } }

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.