14 comments

[ 3.7 ms ] story [ 41.0 ms ] thread
As someone who spent a few weeks looking at how the JVM really works, interfaces and super classes are not a compiler constraint but a JVM one. Sure, you could l could probably generate a lot of bytecode to get around this constraint. Or rewrite the specification for the JVM, and the JVM, and the compiler.

Frameworks like OSGi offer great exetensions to the humble on interface as well.

This article has a really Java-specific slant to it.

Interfaces are more fundamental than classes. An interface is just a contract between a client and its dependencies. This could be as simple as a function signature (callables in Python), a set of methods supported (duck-typing in Ruby/Python/Javascript/Smalltalk, interfaces in Go, or traits in Rust), a set of syntactic forms that are valid (traits in the C++ STL), a set of type-deduction rules (typeclasses in Haskell), or a common message-passing and data-structure format (like Thrift, Protobufs, or Cap'n Proto).

A lot of folks would argue that class is the real mistake in Java & C++, because it conflates the notion of a common interface that can be passed around with means of sharing implementations of that interface. Now, we're obviously not going to get rid of classes in Java. But it's interesting that many of the newer languages like Go and Rust don't have this construct at all, instead promoting interfaces & traits to first-class entities and letting you specify implementation independently.

Rust traits actually do allow you to have "default" implementations of methods, which gives implementers of that trait the option to avoid defining the method themselves.

For example, the trait for overloading the equality operators `==` and `!=` contains two methods, `eq` and `ne`, but `ne` has a default implementation that simply calls `eq` and negates its output. This means you only need to implement one method to get both operators, though you retain the option to implement both manually if you'd like.

Of course, such default implementations are necessarily limited by the fact that a lone trait can assume very little about the type it's being implemented on.

I think that the author misses an understanding of the few concepts, or at least one. This is separation of the concerns.

Even if, as author thinks, that idea of the interface was invented by accidence, it is a good invention.

Because it allows us to clearly to separate the abstract concept from its implementation(s).

Even if Java had multiple inheritance, it should have had also the interfaces to be able to become the usable language it is today.

While interface would allow us to simulate the multiple inheritance, its main benefit is clearly wider.

Disclaimer: the article is by Uncle Bob, whose articles I find harder and harder to read. If nothing else, the condescension in some of them is very annoying. I can't say I respect the guy.

That said,

> Even if Java had multiple inheritance, it should have had also the interfaces to be able to become the usable language it is today.

I have a problem with this assertion. I don't think Java-like interfaces are required for an OOP language to be usable. What about other OOP languages that don't have them, like for example Scala?

Scala has one out of the sight interface:

interface Function { call(...); }. // of course this is a made up syntax.

For most of the cases, this is just enough (as it is also in Java).

I'm sorry, I don't understand your comment. Can you clarify what you mean, using actual Scala syntax if possible? (Just so I understand).

In any case, my point is that since there are usable OOP languages without Java-like interfaces, this kind of interfaces isn't necessary. That is, there are alternative ways of producing usable OOP languages. It doesn't necessarily follow that Java is successful because of its implementation of interfaces.

My point was that, as functions are treated as objects in Scala, you actually have a hidden one method interface behind each function implementation.
Functions are implemented as objects in Scala, but this is an implementation detail. Scala implemented over something else than the JVM could have done first-class functions differently. Also, the notion of "interface" we're discussing here (and Uncle Bob is railing against) is the Java-like interface (i.e. using the actual "interface" keyword that disallows implementation, and not abstract classes). Those are not used in Scala. Therefore, they are not required for successful OOP languages.

Note I think Uncle Bob's condescending tone in TFA is pretty useless. The entire article consists of building a strawman. He really annoys me.

You can see this as an implementation detail or also as a conceptual detail.
I don't think it's conceptual. It's a technical detail. If they had been implemented differently, this would have made little difference to the programmer using Scala.

Again, Objects aren't Java interfaces, so I guess the whole discussion is moot :)

Yes, this is conceptual as you can conceptually regard functions as objects and it may have great benefits as a tool to communicate the idea to the other people.

There are of course other abstractions with their own benefits.

I disagree. Regardless, Objects aren't Java interfaces, so what are we even discussing?

Uncle Bob wasn't arguing against the general concept of an interface, but about its specific meaning in Java.

This article is written and presented in a rather odd way. But still good.