In Dart 3, what do `abstract interface class` and `abstract final class` declare, and which class modifier combinations does the compiler reject?
answer
- abstract, access, mixin, class
- pure interface idiom
- static-only namespace
- base, interface, final are exclusive
- no modifiers on enum
basics
~20 sabstract interface class is Dart's pure interface: implementable elsewhere, never extended or constructed. abstract final class cannot be instantiated directly or subtyped outside its library, suiting static-only holders. Rejected: two of base/interface/final, sealed with any of them or abstract, and mixin with interface, final or sealed.
solid answer
~40 sModifiers stack in a fixed order: optional `abstract`, then at most one of `base`, `interface`, `final`, `sealed`, then optional `mixin`, then `class`. `abstract interface class PaymentGateway` is the idiomatic pure interface: other libraries may only `implements` it, and it may have abstract members. `abstract final class` cannot be instantiated directly anywhere nor subtyped outside its library, so it is used for holders of static members and constants; `dart:core` declares `String`, `int` and `double` as `abstract final`. The compiler rejects combinations that are contradictory or redundant: more than one of `base`/`interface`/`final`, `sealed` with `abstract` or with any of those three, and `mixin` with `interface`, `final` or `sealed`. `enum` and `extension type` accept no class modifiers.
go deeper
Recall abstract interface class as Dart's pure interface and that sealed never combines with abstract.
Explain the modifier order and why base, interface and final are mutually exclusive, and when abstract final class fits a static-only holder.
Read unfamiliar declarations quickly in review and choose the least permissive combination that still supports the intended uses.
Standardise modifier combinations across a codebase so contracts, closed types and constant holders are recognisable at a glance.
## The grammar of class modifiers A Dart 3 class declaration can carry several modifiers, but only in one order (dart.dev, "Combining modifiers"): 1. optional **`abstract`** — may have abstract members, cannot be constructed; 2. optional, **at most one** of **`base`**, **`interface`**, **`final`**, **`sealed`** — restrictions on other libraries; 3. optional **`mixin`** — can be mixed in; 4. the **`class`** keyword. Only `base` may precede a `mixin` declaration (`base mixin`). The modifiers do not apply to `enum`, `typedef`, `extension` or `extension type` declarations. ## `abstract interface class`: the pure interface Dart has no separate `interface` keyword for declaring contracts; every class exposes an implicit interface. Before Dart 3, a reader could not tell whether an abstract class was meant for extending or implementing. `abstract interface class` settles it: ```dart abstract interface class PaymentGateway { Future<void> charge(int cents); } ``` - other libraries may **implement** it; - they may **not extend** it, so they cannot inherit code from it; - nobody can **construct** it, because it is abstract. dart.dev calls this the most common use of `interface`. `dart:core` itself declares `List`, `Map`, `Comparable` and `Exception` as `abstract interface class`. ## `abstract final class`: closed and non-instantiable `abstract final class` cannot be instantiated directly anywhere (like any abstract class, it may still expose factory constructors), and it cannot be extended, implemented or mixed in outside its library. Two uses: - **A namespace for static members**, such as payment limits or currency constants, that nobody should instantiate or subtype: ```dart abstract final class PaymentLimits { static const int maxCents = 1000000; static const int minCents = 50; } ``` - **A closed type whose instances come only from the declaring library**, which is how `dart:core` declares `String`, `int`, `double` and `BigInt`: you can use them, but you cannot implement `String` yourself. ## Combinations the compiler rejects | Combination | Why it is invalid | |---|---| | two or more of `base`, `interface`, `final` | they control the same two capabilities, so they are mutually exclusive | | `sealed` with `abstract` | `sealed` is already implicitly abstract (analyzer: `abstract_sealed_class`) | | `sealed` with `base`, `interface` or `final` | `sealed` already blocks every outside subtyping, so they are redundant | | `mixin` with `interface`, `final` or `sealed` | those modifiers prevent mixing in, which `mixin` exists for | | any modifier on `enum` | enums are never extended, implemented or mixed in | | any modifier on `extension type` | extension types are only implemented by other extension types | ## Valid combinations worth knowing - `abstract base class` — can be extended, not implemented, not constructed. - `abstract interface class` — the pure interface above. - `abstract final class` — static holders and closed types. - `base mixin class`, `abstract mixin class`, `abstract base mixin class` — mixin classes with restrictions (mixins are covered in their own topic). - `sealed class` — alone; never with another access modifier. ## Reading declarations in an interview Interviewers often show a declaration and ask what outside code can do. Work left to right: 1. `abstract` or `sealed` present? Then no one can construct it. 2. Which access modifier? `base` keeps extend, `interface` keeps implement, `final` and `sealed` keep neither. 3. `mixin` present? Then it can also appear after `with`, unless `base` limits implementers. ## Version note All modifiers other than `abstract` need a library language version of 3.0 or later. Applying them to a published API is a breaking change and calls for a major version.
- In Dart 3, how does an abstract final class differ from a class with only a private constructor for holding constants?A private constructor stops outside construction but still lets other libraries `implements` the class. `abstract final class` forbids direct instantiation everywhere and every kind of outside subtyping, and says so in the declaration instead of relying on a convention.
- In Dart 3, why is `abstract interface class` preferred over a plain `abstract class` for a contract?A plain abstract class can be both extended and implemented, so readers cannot tell which is intended, and extenders couple to any code you later add. `interface` states that implementing is the only supported use and stops outside code from inheriting method bodies.
saying these in an interview costs you the question
- abstract sealed class is the correct way to write a sealed type.
- Dart has a standalone interface keyword separate from class.
- A class can be both final and base for extra safety.
- Enums can be marked sealed to restrict their values.
- abstract final class can still be extended in other libraries.