The Artima Developer Community
Sponsored Link

News & Ideas Forum (Closed for new topic posts)
Multiple Inheritance and Interfaces

15 replies on 2 pages. Most recent reply: Oct 4, 2005 3:04 AM by Lee Powell

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 15 replies on 2 pages [ 1 2 | » ]
Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Multiple Inheritance and Interfaces Posted: Dec 15, 2002 7:22 PM
Reply to this message Reply
Advertisement
Artima.com has published Part I of an interview with Scott Meyers in which he discusses 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.

http://www.artima.com/intv/abcs.html

Here's an excerpt:

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 interfaces are an interesting idea.

What do you think of Scott's comments? In particular, what do you think of Scott's take on multiple inheritance and interface classes in C++? Also, do you think the C++ community erred in focusing on exceptions, templates, and the STL instead of building large libraries like the Java community?


Andre Mesarovic

Posts: 1
Nickname: andrem
Registered: Dec, 2002

Re: Multiple Inheritance and Interfaces Posted: Dec 15, 2002 9:55 PM
Reply to this message Reply
Clemens Szyperski in his book "Component Software" (p. 96) succinctly summarized the problem as consisting of:
1. Implementation Inheritance (subclassing)
2. Interface Inheritance (subtyping)

Interface Inheritance obviously avoids the whitebox "diamond problem" issues with Implementation Inheritance, but still shares general inheritance issues of name clashes between superclasses that contain an identical method name.

I find this formal distinction highly useful and precise. Java actually *does* have multiple inheritance - rather than being implementation inheritance it is interface inheritance. C++ does not have a clear distinction between interface and inheritance.

Jason Clarke

Posts: 1
Nickname: jasonc
Registered: Dec, 2002

Re: Multiple Inheritance and Interfaces Posted: Dec 16, 2002 8:10 AM
Reply to this message Reply
I think that there maybe more to the apparent lack of interest in interfaces in the C++ community than Scott describes.

In C++, the style of interface programming used in Java (and C#) is generally less used (less useful?). Templates are typcally used instead.

As I understand it, interfaces are a formal statement of 'capability' or of conformance to a particular design idiom. For example, in C# the IComparable interface (Comparable in Java, I think) is used to specify that a class can be ordered.

In C++ you would be unlikely to write code using this approach. Instead you would typically use a templated method that relies either on a class's < operator for 'natural' ordering or on some functor object to provide custom ordering. (The std::sort algorithm provides an obvious example).

Vincent O'Sullivan

Posts: 724
Nickname: vincent
Registered: Nov, 2002

Re: Multiple Inheritance and Interfaces Posted: Dec 18, 2002 8:47 AM
Reply to this message Reply
Looks like another good interview with one of programming's 'movers and shakers' but please, make sure you spell out all the abbreviations the first time that you use them. Here in the UK, an ISA is a common financial instrument. I had to look up its programming context to properly follow the interview.

Vince.

Matt Gerrans

Posts: 1153
Nickname: matt
Registered: Feb, 2002

Re: Multiple Inheritance and Interfaces Posted: Dec 18, 2002 2:17 PM
Reply to this message Reply
Actually, I must admit I was a little confused when I first saw ISA as I perused (yes, perused) the interview (I was thinking of the PC bus architecture). In this context, it wasn't even an acronym, it conveying the "is-a" concept.

I think Scott hit on a fascinating point at the end of this interview. I wonder to what extent the libraries are more important than the language. Microsoft seems to think (ostensibly) that they are in their promotion of .Net, where they are trying (again, ostensibly) to sell the idea of language agnosticism.

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: Multiple Inheritance and Interfaces Posted: Dec 18, 2002 11:05 PM
Reply to this message Reply
> Looks like another good interview with one of
> programming's 'movers and shakers' but please, make
> sure you spell out all the abbreviations the first time
> that you use them. Here in the UK, an ISA is a common
> financial instrument. I had to look up its programming
> context to properly follow the interview.
>
Sorry Vince. I do try to spell out the abreviations the first time I use them, but I missed ISA. I mean I missed ISA (short for "is a"). I'll fix that tonight when I get a direct connection to the internet. The real problem is that I ran out of time last week and my editor didn't get a chance to fix my mistakes. I keep thinking I'm going to get ahead of schedule, but somehow it never happens. Either it's a law of the universe, or at least a law of my personality.

Nevertheless, please do post or email me if something is confusing in an article. One nice thing about publishing on the web is that mistakes can be corrected, confusing text can be clarified.

Arnold deVos

Posts: 18
Nickname: arnoldd
Registered: Dec, 2002

Interfaces vs. ABC Posted: Jan 6, 2003 4:12 PM
Reply to this message Reply
There is a seldom-mentioned difference between data-less, abstract base classes (ABC in C++ or Java) and Java interfaces.

If I inherit an ABC my decendents or I must implement its methods. Not so if I inherit an interface. Implementations may be supplied by my ancestors as well as my decendents.

Given this, I find it useful to think of adding and interface to a class as "tagging" or "describing" rather than "inheritance", "specialisation" or "extension".

The flavour is brought out when you consider that in Java one can non-intrusively tag an existing implementation, C, with an new interface, I, by creating a class that extends C and implements I. No delegation required.

Arnold deVos

Posts: 18
Nickname: arnoldd
Registered: Dec, 2002

Interfaces vs. ABC Posted: Jan 6, 2003 4:22 PM
Reply to this message Reply
There is a seldom-mentioned difference between data-less, abstract base classes (ABC in C++ or Java) and Java interfaces.

If I inherit an ABC my decendents or I must implement its methods. Not so if I inherit an interface. Implementations may be supplied by my ancestors as well as my decendents.

Given this, I find it useful to think of adding and interface to a class as "tagging" or "describing" rather than "inheritance", "specialisation" or "extension".

You could say this is just part of Java'a solution to the diamond-shaped inheritance problem. But the real flavour is brought out when you consider that in Java one can non-intrusively tag an existing implementation, C, with an new interface, I, by creating a class that extends C and implements I. No delegation required.

Chris Morris

Posts: 1
Nickname: chrism
Registered: Jan, 2003

Re: Interfaces vs. ABC Posted: Jan 7, 2003 1:41 AM
Reply to this message Reply
In Eiffel, when you implement an inherited method, you can also rename it. If two ancestor classes or interfaces have methods which happen to have the same name, they can still be implemented by different methods of the child class.

One great result is that you can implement the same listener interface several times, with different methods for different event sources. This seems like a cleaner solution than anonymous subclasses.

It relies on a different dispatch mechanism. In Java, the method table is an attribute of an object. This is possible because the method table of an ancestor class is always a prefix of the method table of the inheriting class. That is why the dispatch method is different, and less efficient, for a call to an interface reference.

It is more correct to understand the method table as an attribute of a reference. Casting a reference to a new type means making a new reference to the same object but with a different method table. Then the name of a method only need exist at compile time.

C# copied Java in this - it's derivative nature is shown best by the fact that it inherits all of Java's weaknesses.

Bill Venners

Posts: 2284
Nickname: bv
Registered: Jan, 2002

Re: Interfaces vs. ABC Posted: Jan 11, 2003 1:24 AM
Reply to this message Reply
> In Eiffel, when you implement an inherited method, you can
> also rename it. If two ancestor classes or interfaces have
> methods which happen to have the same name, they can still
> be implemented by different methods of the child class.
>
I had heard this about Eiffel.

> One great result is that you can implement the same
> listener interface several times, with different methods
> for different event sources. This seems like a cleaner
> solution than anonymous subclasses.
>
I'm not sure it would be easier to understand to understand a class that implemented the same interface several times and changed the names of the methods. Seems like you'd always have to do an extra step of figuring out what the name change has been.

> It relies on a different dispatch mechanism. In Java, the
> method table is an attribute of an object. This is
> possible because the method table of an ancestor class is
> always a prefix of the method table of the inheriting
> class. That is why the dispatch method is different, and
> less efficient, for a call to an interface reference.
>
I'd say the method table is an attribute of the class, not the object.

> It is more correct to understand the method table as an
> attribute of a reference. Casting a reference to a new
> type means making a new reference to the same object but
> with a different method table. Then the name of a method
> only need exist at compile time.
>
Can you clarify what you mean by this?

> C# copied Java in this - it's derivative nature is shown
> best by the fact that it inherits all of Java's
> weaknesses.

Not that this is much of a weakness, but Ken Arnold always complains that Java's Cloneable interface is mispelled. It should be Clonable. I was rather amused to discover that the corresponding interface in C# is ICloneable. A Jini guy I mentioned this to said it gives one the impression that someone copied Jimmy's homework, including the mistakes.

Rick Wildes

Posts: 1
Nickname: rickw
Registered: Sep, 2003

Re: Multiple Inheritance and Interfaces Posted: Sep 8, 2003 7:01 PM
Reply to this message Reply
I've found small utility classes useful with multiple inheritance in C++. An example of an untility class I'll inherite from even if a class already has a base is my compare helper class:



template<class DERIVED, class COMPARED = DERIVED>
struct CompareHelper
{
bool operator ==(const COMPARED &d2) const
{
return (static_cast<const DERIVED *>(this)->Compare(d2))==0;
}
bool operator >=(const COMPARED &d2) const
{
return (static_cast<const DERIVED *>(this)->Compare(d2))>=0;
}
bool operator <=(const COMPARED &d2) const
{
return (static_cast<const DERIVED *>(this)->Compare(d2))<=0;
}
bool operator !=(const COMPARED &d2) const
{
return !((*this) == d2);
}
bool operator <(const COMPARED &d2) const
{
return !((*this) >= d2);
}
bool operator >(const COMPARED &d2) const
{
return !((*this) <= d2);
}
};


I'll then inherite from this class for each type I want to overload the standard compare operators for.



class my_class
// get compare operators for my class
: public CompareHelper<my_class>
// get compare operators for long type
, public CompareHelper<my_class, long>
{
//<<Define privte here...>>
public:
//<<Define rest of public here...>>

int Compare(const my_class &rhs) const;
int Compare(long rhs) const;
};

int main()
{
my_class c1;
my_class c2;
long l = 9;

if(c1 > c2)
{
//Put greater then code here...
}

if(c1 == l)
{
//Put equal to code here...
}

return 0;

}


Note: the compare helper class is not an ABC. This is to avoid the overhead of the virtual call to Compare().

Joseph Coffland

Posts: 3
Nickname: jcoffland
Registered: Oct, 2003

Re: Multiple Inheritance and Interfaces Posted: Oct 1, 2003 1:11 PM
Reply to this message Reply
There is one problem I run into repeatedly in trying to use the Java
interface paradigm in C++.

A C++ class with only pure virtual member functions and no data
doesn't behave at all like a Java interface in at least one important
aspect.

Perhaps an example will explain it best. First I create a C++ style
"interface" class A. Then I create an implementation of A called
AImpl.

class A {
public:
void function1() = 0;
void function2() = 0;
};

class AImpl : public A {
public:
void function1() {// Do something}
void function2() {// Do something}
};


Now I would like to add some functionality to A with a new "interface"
B. I also naturally want to reuse the code I wrote in AImpl. In Java
this is no problem. I just make B extend A then create a new class
BImpl which extends AImpl and implements B. Java doesn't care that
there is an A in the inheritance tree above both B and AImpl. C++
does.

If I make BImpl inherit from both B and AImpl then I have two copies
of A instead of one. A has no data so there is not a big storage
cost, but it is now ambiguous which version of A I am calling through
B as implemented by BImpl.


class B : public A {
public:
void function3() = 0;
};

// In Java this would be 'extend AImpl implement B'
class BImpl : public AImpl, public B {
public:
void function3() {// Do something}
};


Wouldn't it be wonderful if the C++ compiler would realize that one
version of A is still pure virtual and not implemented and the other
version is the implementation? Java does this automatically.


int main(int argc, char *argv[]) {
B *b = new BImpl();

b->function1(); // This is ambiguous.
b->function2(); // This is ambiguous.
b->function3(); // This is of course not!

return 0;
}


Of course I can just map my BImpl functions down to AImpl but this is
a lot of extra typing and if I where to change A I would have to
update BImpl aswell! We then miss the whole point of inheritance.


// An example of mapping BImpl up to AImpl
class BImpl : public AImpl, public B {
public:
void function1() {AImpl::function1();}
void function2() {AImpl::function2();}
void function3() {// Do something}
};


With out this feature is seems that C++ will never be able to fully
reap the benefits of Java interfaces. Maybe one day the standards
committee will be able to wade through all the bureaucracy and add
a 'interface' keyword to C++.

Joseph Coffland

Joseph Coffland

Posts: 3
Nickname: jcoffland
Registered: Oct, 2003

Re: Multiple Inheritance and Interfaces Posted: Oct 1, 2003 1:48 PM
Reply to this message Reply
Funny how things work. Minutes after I posted the message above I found a solution to my problem. If you use virtual inheritance whenever inheriting from a C++ style "interface" you no longer have the problem! There is a good explanation of how to use virtual inheritance here: http://www.parashift.com/c++-faq-lite/multiple-inheritance.html#faq-25.9

Joseph Coffland

Kris Dekeyser

Posts: 1
Nickname: kdekeyser
Registered: Jan, 2004

Re: Multiple Inheritance and Interfaces Posted: Jan 16, 2004 3:30 AM
Reply to this message Reply
Yep, indeed. That is the proper solution and a good case to show why multiple inheritance may be needed.
It occurs to me that- strange enough - in order to implement Java's Interface mechanism in C++, we have to use virtual multiple inheritance.
A problem which I am facing is to port a utility library which uses this scheme extensively to a build environment that does not allow to use virtual inheritance. I'm now down to the "reimplement and delegate" option :-(((
Are there any other design solutions to solve the A-AImpl-B-BImpl diamond in C++ without virtual inheritance and without the reimplement-in-BImpl-and-delegate-to-AImpl solution?

Rastislav

Posts: 1
Nickname: galia
Registered: Mar, 2005

Re: Multiple Inheritance and Interfaces Posted: Mar 10, 2005 4:56 AM
Reply to this message Reply
I would like to stress the importance of using dynamic_cast to navigate between interfaces of the same object.

Having declarations

//////////
struct IA
{
virtual void fnc1() = 0;
};

strcut IB
{
virtual void fnc2() = 0;
};

class Impl : public IA, public IB
{
void fnc1() { std::cout << "Impl::fnc1()" << std::endl; }
void fnc2() { std::cout << "Impl::fnc2()" << std::endl; }
};

Impl obj;
IA* ia = &obj;
////////

one should not use

IB *ib = (IB*)ia;

or

IB* ib = static_cast<IB*>(ia)

since without an aid from RTTI interface 'ia' is not able to determine the layout of the object 'obj'. Correct usage is

IB* ib = dynamic_cast<IB*>(ia);

Flat View: This topic has 15 replies on 2 pages [ 1  2 | » ]
Topic: Contracts and Interoperability Previous Topic   Next Topic Topic: JavaSpaces: Data, Decoupling, and Iteration

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use