I have been playing around with Dart 3 a bit and am a fan of the new class modifiers. But one I can't seem to get my head around: why does interface class
exist? I understand interface mixin
because you can declare abstract members. But you can't do that with an interface class
, at least in the latest alpha.
Specifically, you can do this:
interface mixin A {
void foo();
}
abstract class B {
void bar();
}
But you can't do this:
interface class C {
void foobar(); // compilation error: needs a concrete implementation
}
What is the point of having an interface class
where you will always need provide stub implementations and then implement them later on? When should you use an interface class
over interface mixin
?
This article covers a bit more details. And this question answers it more broadly.
But the summary is, I agree with you, and that's why you should use abstract interface
instead of just interface
(and only ever implement
, not extend
). You'd only use interface
over abstract interface
if you wanted to be able to instantiate it.
interface
extended
abstract
extended
or implemented
abstract interface
+ implements
gives you the best/most limited version of both (for tight scoping). Can't be instantiated and MUST override all method bodies.
What is it: More like a traditional interface. Can only be implemented (not extended). But you can define functions without bodies.
Why you should care: You can define just the “shape” without defining any functionality. There’s nothing hidden in the parent class.
// -- File a.dart
abstract interface class AbstractInterfaceClass {
String name = 'Dave'; // Allowed
void body() { print('body'); } // Allowed
// This is a more traditional implementation
int get myField; // Allowed
void noBody(); // Allowed
}
// -- File b.dart
// Not allowed
class ExtensionClass extends AbstractInterfaceClass{}
// Allowed
class ConcreteClass implements AbstractInterfaceClass {
// Have to override everything
@override
String name = 'ConcreteName';
@override
void body() { print('body'); }
@override
int get myField => 5;
@override
void noBody() => print('concreteBody');
}
// -- File a.dart
interface class InterfaceClass {
String name = 'Dave'; // Allowed
void body() { print('body'); } // Allowed
int get myField; // Not allowed
void noBody(); // Not allowed
}
// -- File b.dart
// Not allowed
class ExtensionClass extends InterfaceClass{}
// Allowed
class ConcreteClass implements InterfaceClass{
// Have to override everything
@override
String name = 'ConcreteName';
@override
void body() { print('body'); }
}