Interfaces are useful because they allow you to switch class implementations while still checking that the type passed in meets the interface requirements.
Take the following (commonly used) example:
interface Quackable { void quack(); }
This defines the requirements of the class that will be passed to the method, for example:
sayQuack(Quackable quackable) { quackable.quack(); }
which allows you to use any implementation of the Quackable object, for example:
class MockDuck implements Quackable { void quack() => print("quack"); } class EnterpriseDuck implements Quackable { void quack() { // connect to three enterprise "ponds" // and eat some server bread // and say "quack" using an messaging system } }
Both of these implementations will work with the sayQuack () function, but significantly less infrastructure is required than the other.
sayQuack(new EnterpriseDuck()); sayQuack(new MockDuck());
I use this template all the time in the Java world when creating solutions that use some kind of enterprise duck. When developing locally, all I just need is to be able to call the sayQuack () function and return some hard-coded, mock data.
Duck seal
Since Dart is not necessarily printed, you actually do not need to use the interface, just writing a class that contains the correct method signature will work (although the tools will not be able to verify it).
class Person { // note: no implements keyword void quack() => "I'm not a duck"; } sayQuack(new Person()); // provides the quack method, so this will still work
All classes are interfaces.
Finally, all classes are also interfaces. This means that although a third-party system can be written without using interfaces, you can still use a specific class, as if it were an interface.
For example, imagine the following corporate library:
class EnterpriseDuck { // note: no implements keyword void quack() { // snip } } sayQuack(EnterpriseDuck duck) { // takes an instance of the EnterpriseDuck class duck.quack(); }
And you want to pass the false duck to the sayQuack method so that the validating type can validate. You can create your mockDuck to implement an interface implied by EnterpriseDuck just by using EnterpriseDuck as an interface:
class MockDuck implements EnterpriseDuck { void quack() => "I'm a mock enterprise duck"; }
Multiple inheritance
In terms of multiple inheritance, this is not possible in Dart. However, you can implement several interfaces and provide your own implementations of the necessary methods, for example:
class MultiDuck implements Quackable, EnterpriseDuck, Swimable { // snip... }
Interfaces may have default classes.
As you use Dart, you will find that most of the โclassesโ are actually interfaces. List, String, etc. - all interfaces with default implementation. When you call
List myList = new List();
you are actually using the List interface, and the new keyword redirects from the interface to the default base list implementation.
Regarding team development
Interfaces are useful in teamwork, even in the open source world. The interface defines the methods and properties that you must create in order for your component to work with my component. You can create your own test implementation of this interface, and I can implement my specific implementation of this interface, and when we both finish, we can integrate. Without a published shared interface, I will need to provide a specific implementation before you can get started.
Hope this helps!