This article was originally published on my blog.
Interfaces are one of the most important features of a lot of programming languages. A lot of their features won't be available without that small keyword.
But working with different languages we can spot two different paradigms in how interfaces are implemented in them. I have decided to name them the "Implicit implementation" and the "Explicit implementation".
Explicit implementation
Explicit implementation is the most straight forward one from the two to spot. The most prominent example is this approach used by the java
language.
The idea is fairly simple, after you define an interface, you need to explicitly specify that you are implementing it by the current class. As an example.
interface Geometry {
float area();
}
class Rectangle implements Coordinates {...}
Although this approach make the code easier to read, since by just glancing at the code we can guess that this class have the methods and attributes defined in the interface.
The limitations of explicit implementation
Let's imagine you have this code in Typescript
.
class Point {
x: number;
y: number;
...
}
interface Coordinates {
x: number;
y: number;
}
function getX(_object: Coordinates): number {
return _object.x;
}
To test it we can execute:
const point: Point = new Point();
console.log(getX(point));
Any Typescript
developer know that this type of code works. However in the java
world it does not. For the languages that rely on the explicit implementation scheme, an error will be thrown at you. for them, even if the Point
class have apparently the requirements to be considered as a Coordinates
implementation, it is not.
You may not see the problem, but it become crucial when the class you wanna use is from a library but the interface is yours.
Implicit implementation
To solve this sticky situation, more and more languages rely on implicit implementation. In those type of languages, like Typescript
or go
, the compiler see if the class fulfill the requirements specified by the interface, and not if it implements it.
This languages have decided to sacrifice readability, unless you know all the interfaces of your code, you can not know if a class follow an interface specification or not.
A quick demonstration from the go language.
type Geometry interface {
area() int
}
type rectangle struct {
x, y int
}
func (r rectangle) area() int {
return r.x * r.y
}
func getArea(_object Geometry) {
return _object.area()
}
For testing purposes:
func main() {
r := rectangle{x: 1, y: 2}
getArea(r)
}
And as expected it works without much effort, and without the hassle of having to explicitly declare the implementation of the interface.
__
I hope that this article was a quick peek to discover one of the many questions a languages designer have to ask himself before starting to make it's own language. (Although I agree that interfaces may not be the first thing he will start with ;) !). However it shows the two most common approaches, one more focused on readability, the other on functionality and extensibility. For you, which one of those implementations do you prefer ?
Top comments (0)