skip to content

Extends & Implicit Interfaces

Dart has single inheritance with extends, and every class is an implicit interface you can implement. Interviewers probe what implements makes you re-declare that extends would not.

part ofDartoverview, primer and where to startread it →
on this pageshow

explore

questions

5

In Dart, what is the difference between extends and implements, and what must a class that implements another class re-declare?

level: juniorimportance: must knowfreq 74%

answer

  1. every class is an interface
  2. one superclass, many interfaces
  3. implements inherits no code
  4. fields count as getters and setters
  5. constructors and statics are not in it

basics

~20 s

extends makes a subclass that inherits the superclass's implementation, and a class has exactly one superclass. implements only adopts the implicit interface of each listed class, so the class must itself implement every instance member, fields included, but not constructors or statics.

solid answer

~40 s

Every Dart class implicitly defines an interface: all its instance members, including the getters and setters that its fields induce. `extends` gives you that interface **and** the implementation — you inherit method bodies and fields, override what you need and call `super`. Dart allows only one superclass. `implements` gives you the type only: the class becomes a subtype of each listed class but inherits no code, so it must provide every instance member itself — including `width` and `height` if the other class declares them as fields. Constructors and static members are not part of an interface. You may implement several classes at once, and the same class cannot appear in both `extends` and `implements`. Private members of a class from another library cannot be implemented by you at all.

go deeper

for a junior

Recall that extends inherits code from one superclass while implements adopts any number of implicit interfaces and inherits nothing.

for a middle

Explain what the implicit interface contains, why fields must be re-declared as fields or getters, and why constructors and statics are excluded.

for a senior

Judge the coupling: implementing a concrete class you do not own breaks whenever it grows, and private members across libraries fail at runtime.

for a principal

Decide which types in a shared codebase are published as contracts to implement and which are meant only to be extended or used.

## Every class is an interface Dart has no separate interface declaration of the kind some languages use. Instead, **every class implicitly defines an interface** containing all of its **instance members**: methods, operators, getters and setters — and, because every field induces a getter (plus a setter unless it is `final`), its fields too. Constructors and `static` members are not part of that interface. That gives a class two ways to relate to another class. ## `extends`: type plus implementation ```dart abstract class Shape { double get area; String describe() => '$name: ${area.toStringAsFixed(2)} m2'; String get name; } class Rect extends Shape { Rect(this.width, this.height); final double width, height; @override String get name => 'rect'; @override double get area => width * height; } ``` `Rect` inherits `describe()` without restating it. Key properties of `extends`: - **Single inheritance**: a class has exactly one superclass (implicitly `Object` if none is named). - Inherited members come with their **implementations**; the subclass overrides selectively. - The subclass must call a **generative superclass constructor**, explicitly or implicitly. - `super.member` reaches the superclass implementation. ## `implements`: type only ```dart class TracedOutline implements Rect { TracedOutline(this.width, this.height); @override final double width, height; @override String get name => 'traced'; @override double get area => width * height * 0.98; @override String describe() => 'traced outline, ${area.toStringAsFixed(1)} m2'; } ``` `TracedOutline` is usable anywhere a `Rect` is expected, but it inherits **nothing**: it had to re-declare `width`, `height`, `name`, `area` **and** `describe()`, including the member `Rect` itself inherited from `Shape`. Key properties: 1. A class may implement **many** interfaces: `class Tile implements Rect, Comparable<Tile>`. 2. Every instance member of every listed interface must be implemented, or the analyzer reports missing concrete implementations — unless the class is `abstract`, or overrides `noSuchMethod` so the compiler fills the gaps with forwarders. 3. **No constructors** are involved; the implementing class writes its own. 4. The same type cannot appear in both `extends` and `implements` (`implements_super_class`), nor twice in `implements` (`implements_repeated`). ## What the difference costs | | `extends Rect` | `implements Rect` | |---|---|---| | Subtype of `Rect` | yes | yes | | Inherits method bodies | yes | no | | Inherits field storage | yes | no — re-declare as fields or getters | | How many allowed | one | any number | | Runs `Rect`'s constructor | yes | no | | `super.area` available | yes | no | | New member added to `Rect` later | inherited automatically | implementers break until they add it | The last row is the practical one: implementing a class ties you to its **whole** interface, so every new member its author adds is a compile error in your code. ## Private members across libraries A class's interface also contains its **private** members, but only code in the same library can name them. If you implement a class from another library that has private members, you cannot provide them. Should that library call one of them on your object, the call fails at runtime with a `NoSuchMethodError`. Preventing that situation is one purpose of Dart 3's class modifiers. ## When to use which - Use `extends` when the subclass **is a specialised version** and should reuse behaviour: `Square extends Rect`. - Use `implements` when you need **substitutability without the implementation** — a test fake, an adapter over another data source, or conforming to several unrelated contracts such as `Comparable`. - Prefer implementing **abstract** classes designed as contracts; implementing a concrete class couples you to details its author may change.

  • In Dart, can a class both extend one class and implement others?
    Yes: `class Square extends Rect implements Comparable<Square>` is valid. It inherits `Rect`'s implementation, and must itself implement `compareTo` for `Comparable`. The one restriction is that the superclass cannot also be listed in `implements`, and no type may be listed twice there.
  • In Dart, what happens to a class that implements a concrete class when that class gains a new public method?
    It stops compiling. Implementing adopts the entire interface without any implementation, so the new member is missing from the implementer until someone adds it. A subclass that extends the class would simply inherit the new method. That is why implementing a class you do not own is a stronger coupling than it looks.

saying these in an interview costs you the question

  • A class that implements another inherits its method bodies
  • Fields are not part of Dart's implicit interface, only methods
  • Dart supports multiple inheritance with extends A, B
  • An implementing class must also re-declare the other class's constructors
  • You need a separate interface declaration before a class can be implemented
open as a page

In Dart, what makes a class abstract, how do you declare an abstract member, and what must a concrete subclass do with it?

level: juniorimportance: should knowfreq 60%

basics

~20 s

A class marked abstract cannot be instantiated and may declare members with no body, written as a signature ending in a semicolon. A concrete subclass must implement every inherited abstract member, or be declared abstract itself.

open as a page

In Dart, how do fields, getters and setters relate in a class's interface, and why can a field become a getter without breaking callers?

level: middleimportance: should knowfreq 38%

basics

~20 s

Every Dart field induces an implicit getter, plus a setter unless it is final, and interfaces contain those accessors rather than storage. So a field and a getter are interchangeable to callers, and either can implement or override the other.

open as a page

In Dart, what rules must an overriding member follow, what does the @override annotation actually check, and what does a super call invoke?

level: middleimportance: should knowfreq 45%

basics

~20 s

An override may return a subtype and accept supertypes of the original parameters, with the same positional parameter count. @override is an optional annotation the analyzer checks, reporting it if nothing is overridden. super.m() calls the superclass chain's implementation of m.

open as a page

In Dart, when does an overridden noSuchMethod actually run, and why can a class with one implement an interface without implementing its members?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

noSuchMethod runs when a call reaches a member the object lacks: via a dynamic receiver, or via a member its static type declares but its class leaves unimplemented while overriding noSuchMethod. Such classes get compiler-generated forwarders, so they compile without implementing the interface.

open as a page