interface
s.
Scott Meyers is one of the world's foremost experts on C++ software development. He wrote the best-selling Effective C++ series (Effective C++, More Effective C++, and Effective STL), wrote and designed the Effective C++ CD, is consulting editor for Addison Wesley's Effective Software Development Series, and is a member of the advisory board for Software Development magazine. A programmer since 1972, he holds an M.S. in Computer Science from Stanford University and a Ph.D. from Brown University.
In this four-part interview, which will be published in weekly installments, Meyers gives his views on many topics of object-oriented design, including the use of multiple inheritance in light of Java's interface
, designing minimal and complete interfaces, public data members and contracts, and the utility of const
. In this initial installment, Meyers indicates how his view of multiple inheritance has changed with time, describes the C++ community's take on Java's interface
, and points out a schism of focus between the C++ and other prominent development communities.
Bill Venners: Your book Effective C++ was the first book on object-oriented programming that I bought, and I picked up a lot of fundamentals from it. For example, I had never heard of ISA (as in an ArrayList
IS A List
) before reading your book. Your guideline, "Make sure public inheritance models ISA" was my first introduction to that idea. I probably hadn't even heard that data should be private before reading your book.
I read Effective C++ back in the early 90s, when I was moving from C to C++. Much of my philosophy of object-oriented design originally came from your book, but since then I've changed the way I think about design in some ways. I'm curious how your ideas of object-oriented design may have changed or evolved since you wrote Effective C++. My first question for you involves multiple inheritance and interface
s.
Any time you used the word "judiciously" in an Effective C++ guideline it really scared me away. For example, you said, "Use private inheritance judiciously." I didn't just use private inheritance judiciously, I never used it at all. You said, "Use multiple inheritance judiciously." In five years of C++ programming, I never once used multiple inheritance.
My attitude about multiple inheritance in C++ didn't come only from your book. Most of my friends who were programming in C++ shared that attitude. The way we thought about multiple inheritance was that given two full blown classes, each of which could be instantiated, you create a third full blown class that inherits from the other two. That class structure, which is what we thought of when we thought of multiple inheritance, has all the problems you describe in Effective C++. I wasn't determined to avoid multiple inheritance in C++ at all costs, but in five years I never encountered a situation in which I felt inheriting from multiple base classes made sense in my designs.
When I moved from C++ to Java in early 1996, however, I encountered Java's interface
. I quickly learned the mechanics of Java's interface
—I understood how it worked—but I didn't know how to design with it. Here was multiple inheritance again, but not the full blown kind of multiple inheritance I was used to in C++. With Java's interface
construct, I could multiply inherit interface but not implementation. In the C++ terminology you used in Effective C++, Java only let me multiply inherit from abstract base classes (ABCs) that had no data members and only pure virtual functions.
Bill Venners: Why did Java only allow multiple inheritance of interface? How should I apply interface
s in Java designs? I didn't know, but I did soon realize that although in five years of C++ I never once used multiple inheritance, I was finding Java's special kind of multiple inheritance very useful. The process of struggling with Java's interface
changed the way I think about object-oriented design in general. Were I to go back to C++ now, I would make much more use of ABCs that have no data members and only pure virtual functions.
I'm curious if you've had any similar transformation regarding multiple inheritance. Is there anything you would say about ABCs or multiple inheritance and their place in designs now that you didn't say 10 years ago?
Scott Meyers: I don't have a lot that is new, but I would say two things. First, if you look at interface
s in Java or .NET, in addition to being ABCs, interface
s also have no data. I have come to appreciate that if you use abstract base classes and eliminate any data from them, then a lot of the difficulties of multiple inheritance that I wrote about just go away, even in C++.
I happen to think one of the contributions of Java was getting rid of some of the baggage that comes with multiple inheritance in C++. I'm guessing, since I'm not a Java guy, that the creators of Java looked at the multiple inheritance model of C++. They said, "This has some good things, but it has some baggage too. So we're going to try to find a way to have the good stuff and throw away the baggage." That's essentially what an interface
is. It is an abstract base class that doesn't have any of the things that tend to give rise to trouble in C++, because it doesn't have any data. I think that's an interesting idea. So I think interface
s are an interesting idea.
Second, at the time in 1991 when I wrote that multiple inheritance guideline in Effective C++, a huge debate about multiple inheritance was raging in the C++ community. My advice to use multiple inheritance judiciously was based on two observations. First, at that particular time no one had really come out with a compelling example in which multiple inheritance was useful and there was no competing design that was at least as good. Second, even some of the people who had used multiple inheritance didn't have great things to say about it. Notably, Jerry Schwartz, who had implemented the IO streams library based on multiple inheritance, had publicly said that if he had it to do over again he would not use multiple inheritance. He would find some way to get rid of the multiple inheritance.
At the time I wrote that guideline in 1991 I had never seen a compelling example for the use of multiple inheritance. I knew about the difficulties with multiple inheritance that I have written about. At the time I was not talking about interface
s, because they didn't exist in that name. And somebody like Jerry, who had a lot of experience with multiple inheritance, was saying if he had to do it over again he would have found a way to get rid of the multiple inheritance. That was the reason for my advice about multiple inheritance at that time.
A certain amount of time has gone by. My feeling about multiple inheritance now is that as long as you go into it with your eyes open, so you understand the kinds of things I wrote about in the book, especially if you are using interface
-like classes that have no data, you will be able to side-step most of those difficulties. So I'm less down on multiple inheritance now.
Frankly, though, my advice would not change. I would still say use multiple inheritance judiciously, because if you have a choice between a single inheritance based design and a multiple inheritance based design, I think most of the time the single inheritance based design will be simpler. And I like simpler better than more complicated. But perhaps you are faced with a multiple inheritance based design and a single inheritance based design, and the multiple inheritance based design strikes you as being cleaner or in some other way advantageous. As long as you've taken into account the difficulties with multiple inheritance that have been talked about, probably you've eliminated them by using interface
classes, then I would say fine, follow your design instinct and use the multiple inheritance. So my tone on multiple inheritance has softened a little bit.
Bill Venners: If public inheritance means ISA, what does ABC inheritance mean?
Scott Meyers: ABC inheritance still means ISA. Public inheritance always means ISA. That's just what it means. If you are inheriting from an ABC, all you are saying is, "I'm going to inherit an interface, and that particular interface can never be instantiated." But in C++ there can still be data in the ABC, and there are certainly going to be virtual member functions, so you still have behavior. Publicly inheriting from an ABC just means that every instance of my class IS AN instance of this ABC. That's what the inheritance is asserting. That's what ISA means. "I am one of those." The fact that the base class is an ABC says, "By myself, I am not complete enough to be instantiated." But those are orthogonal statements.
Bill Venners: Let's define ABC. ABC means abstract base class. So what would you call in C++ that special case of an ABC that has no data and nothing but pure virtual functions, which have no implementation.
Scott Meyers: The C++ community does not have a name for that. There is no commonly accepted term for that kind of class. Some people call it "interface class." Some people quite incorrectly call it a virtual base class, but as long as we are among friends and know what we are talking about, that's OK. But the notion of essentially a C++ implementation of an interface
in Java or C# does not have a name in C++.
Bill Venners: I found in coming to Java that interface
s are a very useful tool in designs. Were I to go back to C++, I would use them a lot more. That's how I would now use multiple inheritance in C++.
Scott Meyers: Interface
s you mean?
Bill Venners: Interface classes, or whatever you want to call them. I am wondering to what extent the C++ community has discovered this usefulness that I feel interface
s provide in Java. I see it as something that's generically useful in object-oriented design. The fact that Java had a special construct called interface
forced me to figure out what to do with it in 1996. That's how I discovered this useful tool of OO design. But if the C++ community doesn't have a special name for it, then maybe that community really hasn't been turned on by interface
s.
Scott Meyers: I think two things have happened. First, experienced designers of frameworks and libraries had already decided that that particular kind of abstract base class was particularly useful. They were using them. They just didn't have a particular name for them. Second, in the past last five or six years, almost all of the attention in the C++ community has been focused on two features of the language: exceptions and templates. Templates and the standard template library (STL) have received a huge amount of attention. As a result, the object-oriented part of the language has not received very much attention. If I had to give a reason why there doesn't seem to be a common name for interface classes in the C++ community, I would say probably the most important reason is simply because the entire language community has been focused so much more on these other features, exceptions and templates, that they did not know how to use.
I'm going to speculate now, because I haven't been watching Java and I've just got my feet a little bit wet in .NET. But I would say that while the C++ community was focusing on templates, the STL, and exceptions—oddly enough the three are wrapped up together pretty closely—what they were not doing was component-based development. For example, there is no huge collection of class libraries for C++. The standard library for C++ is pretty impoverished. In the meantime, the rest of the world was busy creating huge class libraries that let you write all kinds of really neat applications without having to write very much code. Certainly Java is famous for its libraries. .NET has a huge number of libraries.
I think a schism existed between the C++ community, which was still focused on language issues, and the other prominent development communities, which pretty much left the language alone. Java already had exceptions, but didn't have templates and had nothing like the STL. Yet the Java community focused on writing a whole bunch of libraries that everybody can assume will exist everywhere, libraries that will let you write applications really quickly. The end result is, we have templates in C++, but there's no way to write user interfaces or talk to databases. Java has no templates, but you can write user interfaces up the wazoo and you can talk to databases with no trouble at all.
Effective C++, Second Edition, by Scott Meyers is at Amazon.com at:
http://www.amazon.com/exec/obidos/ASIN/0201924889/
More Effective C++, by Scott Meyers is at Amazon.com at:
http://www.amazon.com/exec/obidos/ASIN/020163371X/
Effective STL, by Scott Meyers is at Amazon.com at:
http://www.amazon.com/exec/obidos/ASIN/0201749629/
Effective C++ CD, by Scott Meyers is at Amazon.com at:
http://www.amazon.com/exec/obidos/ASIN/0201710919/
Scott Meyer's website contains links to many publications, presentations, books, and other information from Scott:
http://www.aristeia.com/
Images of Persephone, the best dog in the world:
http://www.aristeia.com/Persephone/index_frames.html
Have an opinion? Readers have already posted 15 comments about this article. Why not add yours?
Bill Venners is president of Artima Software, Inc. and editor-in-chief of Artima.com. He is author of the book, Inside the Java Virtual Machine, a programmer-oriented survey of the Java platform's architecture and internals. His popular columns in JavaWorld magazine covered Java internals, object-oriented design, and Jini. Bill has been active in the Jini Community since its inception. He led the Jini Community's ServiceUI project that produced the ServiceUI API. The ServiceUI became the de facto standard way to associate user interfaces to Jini services, and was the first Jini community standard approved via the Jini Decision Process. Bill also serves as an elected member of the Jini Community's initial Technical Oversight Committee (TOC), and in this role helped to define the governance process for the community. He currently devotes most of his energy to building Artima.com into an ever more useful resource for developers.
Artima provides consulting and training services to help you make the most of Scala, reactive
and functional programming, enterprise systems, big data, and testing.