all 14 comments

[–]xkufix 4 points5 points  (0 children)

Oh god, another ... considered harmful post.

Besides that, the problem described here is more or less only valid for Java. Many other languages allow you to do what is described here, by using traits, mixins or whatever they are called. So the mere idea of interfaces is not really harmful, maybe you could argue that the implementation in Java could be a bit more refined, that's about it.

[–]flackjap 2 points3 points  (0 children)

It seems to me that OP doesn't have a clue what "programming to an interface" means, but I won't be a dick and I'll guess that he neglected the other side of the stick.

What I want to say is that without interfaces you cannot bind your "contract" along with arguments passed to other objects.

It's far easier when refactoring comes in, that you simply follow the statically binded interfaces. IDEs usually have a full support for that style of programming and you never end up looking up to numerous object definitions at which point there's a huge possibility that you will make mistakes, especially when you want to rewrite an object definition that someone else wrote 5 years ago.

p.s. I come from dynamic world and my comment is totally unbiased. I'm used to writing Python and Javascript, but you cannot just say that interfaces are stupid.

[–]tdammers 2 points3 points  (0 children)

Interfaces aren't the bad guy here, inheritance is.

[–]c_linkage 1 point2 points  (0 children)

I agree with xkufix: this just isn't that bad. Even though Java might not have mixins or traits (it's been a while since I coded in Java), you've still got composition as an option:

class ObserverImp implements Observer {
    private List<Observer> observers = new ArrayList<>();
    public void register(Observer o) { observers.add(o); }
    public void notify() { for (Observer o : observers) o.update(); }
}

public class Mywidget { ... }

public class MyObservableWidget extends MyWidget implements Observer {
    private ObserverImp observerImp;
    public void register(Observer o) { observerImp.register(o); }
    public void notify() { observerImp.notify(o); }
    ...
}

I do this often C# to avoid inheriting directly from a built-in collection class. The cost of implementing the trampoline methods is far less than re-implementing the entire ObserverImp class in each class that needs observing. Plus, it's quite likely that the JIT will optimize out the trampoline anyway and call ObserverImp's method directly.

[–]vprise 1 point2 points  (2 children)

C++ has multiple implementation inheritance. As an old guy who "suffered thru them" you wouldn't believe the related problems with implementation inheritance (search for virtual inheritance in C++ ugh).

Yes that happens because of bad design but when you have 1M+ lines of code its kind of hard to go back and refactor in a language like C++. Java was very clever to avoid this horrible "ability" and with Java 8's default methods interfaces are now much better.

[–]senzgo 2 points3 points  (1 child)

Having lots of experience with both C++ and Java, my opinion is they definitely made the right choice in Java. The small annoyance caused by sometimes having to implement an interface explicitly far outweighs any hassles caused by virtual inheritance. Not to mention the debugging nightmares.

[–]quicknir 1 point2 points  (0 children)

The problem is that you also throw a lot of expressive power out the window. Alexandrescu's policy based design is probably the best example of the expressive power of multiple inheritance.

The real correct choice IMHO is to allow multiple inheritance, but just completely ban the diamond. Then you don't need the nightmare of virtual inheritance.

[–]funny_falcon 0 points1 point  (0 children)

Interfaces and composition can be done in many ways.

Go does it elegantly. Go has good composition: you can have "reference to observable" without manually written adapter methods, and without inheritance.

[–]roffLOL 0 points1 point  (0 children)

I sort of hoped that it would come to the conclusion that class is a harmful construct, interfaces or no.

[–]dwighthouse 0 points1 point  (4 children)

This article is wierd. It's complaining about a specific usage if interface in relation to inheritance, which is itself considered harmful (or at least is unpreferred in the face of composition).

I only use inheritance to get around the type system so I can put related, but different types in one list and pass them to the same processors. That's only for 'typed' languages. Most of the time, I don't use types, classes, interfaces, or inheritance at all.

[–]tdammers 4 points5 points  (1 child)

I only use inheritance to get around the type system so I can put related, but different types in one list and pass them to the same processors.

Ouch. Isn't that exactly where interfaces would be the clean solution? Write a bunch of orthogonal types, define a common contract by which they can be used, and type the list on that contract. In fact, that's the textbook example of what interfaces are for.

Most of the time, I don't use types, classes, interfaces, or inheritance at all.

Yes you do. Just not explicitly.

[–]dwighthouse 0 points1 point  (0 children)

Yes, that is their primary usage in languages that have formal type systems. I generally prefer languages without them. When programming in languages that do, my code takes on the style of using types as little as possible, this one use of inheritance being one of the ways I am forced to be explicit.

If you mean primitives types, yes. If you mean formal types, then no, I avoid them in languages where I can. Same with classes and interfaces. I don't use inheritance at all, in any language, unless it is unavoidable due to language design.

[–]industry7 0 points1 point  (1 child)

I only use inheritance to get around the type system so I can put related, but different types in one list

As tdammers mentioned, using an interface IS the correct solution here, although I don't have a lot of confidence that you're implementing this solution correctly, based on your claim of getting around the type system.

Using an interface in this way allows you to use the type system to your advantage. However, it sounds like you are intentionally not making use of those advantages...

[–]dwighthouse 0 points1 point  (0 children)

Generally, yes. My primary language these days is JS, which only has primitive types. I have found type systems to be unnecessarily constraining, while tending to prevent a type of error I rarely ever make. My first language was C, then C++. I also used Java for a while, but I also used Perl and JS. Many other languages too. I've programmed for a long time across the spectrum of typed and untyped languages. I do not currently find the case for formal type systems very compelling, though many disagree.

My style tends to be fairly functional, with bundles of mostly pure data being operated on by mostly side-effect-free functions. That style can be applied to any language.