I was reading Dart’s documentation and I was a little bit confused, maybe because I’m coming from Ruby, as to how to use interfaces. Of course, interfaces are not unique to Dart and there are quite a number of explanations out there on when one should use an interface. This one, for example, seems to be saying that interfaces are only useful when you’re in a team. What is it even supposed to mean in the open source world, where everybody reads and reuses somebody else’s code?
One interesting explanation I’ve seen seemed to be implying that interfaces are used:
- in languages that lack multiple inheritance, and
- for that matter they somehow serve as a workaround for the absence of multiple inheritance.
I don’t understand that. I understand that modules in Ruby are a workaround because they allow me to define real methods with actual bodies. Interfaces only allow me to define what methods a class implementing it should have. What’s the catch? Can anyone tell of a real useful example where I can immediately see the value of using interfaces?
P.S. On a related note, is there a way to use multiple inheritance in Dart?
Update: the interface keyword has since been removed from Dart.
Interfaces are useful because they allow you to switch implementations of a class, whilst still allowing validation that the type being passed in meets the requirements of the interface.
Take the following (often used) example:
This defines the requirements of a class that will be passed to a method such as:
which allows you to make use of any implementation of a Quackable object, such as:
Both of these implementations will work with the sayQuack() function, but one requires significantly less infrastructure than the other.
I use this pattern all the time in the Java world, when building solutions that make use of some “enterprise duck”. When developing locally, all I simply need is to be able to call the sayQuack() function and return some hard-coded, mock data.
Duck typing
Because Dart is optionally typed, you don’t actually need to use the interface, simply writing a class that contains the correct method signature will work (although the tools won’t be able to validate it).
All classes are interfaces
Finally, all Classes are also interfaces. This means that even though a third party system may have been written without using interfaces, you can still use a concrete class as though it were an interface.
For example, imagine the following enterprise library:
And you want to pass a mock duck into the sayQuack method in a way that the type checker can validate. You can create your mockDuck to implement the interface implied by EnterpriseDuck, simply by using the EnterpriseDuck as an interface:
Multiple Inheritance
In terms of multiple inheritance, this is not possible in Dart. You can, however, implement multiple interfaces and provide your own implementations of the required methods, eg:
Interfaces can have default classes
As you use Dart, you will find that most “classes” are actually interfaces. List, String etc… are all interfaces with default implementations provided. When you call
you are actually using a List interface, and the new keyword redirects from the interface to an underlying default List implementation.
With regards to developing in a team
Interfaces are useful in team development, even in the open source world. The interface defines the methods and properties that you should be building so that your component works with my component. You can build your own test implementation of that interface, and I can build my concrete implementation of that interface, and when we’re both done, we can integrate. Without the published, shared interface, I would need to provide my concrete implementation before you could really get started.
Hope that helps!