Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Interfaces and multiple inheritance

5 views
Skip to first unread message

Chris Birmele

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
Hi,

I have a question about interfaces versus multiple inheritance.
Recently I was 'bashed' on another listserver, when I suggested
multiple inheritance is not such a bad idea (the programming language
supports only single-inheritance).

I was told in no uncertain terms that 'interfaces' are the way to go.
Having done a bit of homework, I am confused as to whether interfaces
are a 'workaround' for languages not providing multiple inheritance or
truly a good thing.

The UML user guide describes 'interfaces' as a "collection of
operations that are used to specify a service of a class or a
component; every class may realise many interfaces" (p146)

How does this fit in with the OO design principle that a class should
provide a limited number of well defined services based on the
underlying abstraction? Does it not encourage developers to design
'can-do-all' classes and simply use a number of 'interfaces' to group
services together?

Appreciate any feedback!

Thanks, regards
Chris


Robert O'Dowd

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
Chris Birmele wrote:
>
> Hi,
>
> I have a question about interfaces versus multiple inheritance.
> Recently I was 'bashed' on another listserver, when I suggested
> multiple inheritance is not such a bad idea (the programming language
> supports only single-inheritance).
>
> I was told in no uncertain terms that 'interfaces' are the way to go.
> Having done a bit of homework, I am confused as to whether interfaces
> are a 'workaround' for languages not providing multiple inheritance or
> truly a good thing.

You were bashed by Java fans, I'll bet :-)

Inheritence of multiple interfaces is a subset of multiple inheritence.

With true multiple inheritence is that the behaviour of multiple classes
can be inherited directly. For example, let's say that class A provides
an operation called service_A and class B provides an operation called
service_B.

With multiple inheritence, a class C derived from both A and B will
inherit the implementation of service_A and service_B. There is
no specific requirement for class C to implement anything to
provide those services.

With inheritence of multiple interfaces, a class C that provides
the interfaces of A and B does not inherit any implementation
of the services. It only inherits a contract that says it has
to provide the services.

The choice between the two options is a trade-off. There are many
problems where inheritence of multiple interfaces is adequate. There
are also examples where it is much easier to do it with multiple
inheritence. That really depends on the nature of your class
hierarchy.

Multiple inheritence, if done "properly" is hard work for the language
designer and compiler implementer. Inheritence of multiple interfaces
is much easier to implement. Unfortunately, that reason is the driving
factor behind some languages only supporting inheritence of interfaces.

>
> The UML user guide describes 'interfaces' as a "collection of
> operations that are used to specify a service of a class or a
> component; every class may realise many interfaces" (p146)
>
> How does this fit in with the OO design principle that a class should
> provide a limited number of well defined services based on the
> underlying abstraction? Does it not encourage developers to design
> 'can-do-all' classes and simply use a number of 'interfaces' to group
> services together?
>

The point of interfaces is that they do not, alone, provide the
behaviour. It is necessary, at some point, to implement the behaviour
provided by interfaces. Inheriting interfaces simply says
"I will provide these services". That does not necessarily include
inheriting and reusing an implementation of those services.

-<Automagically included trailer>
Robert O'Dowd Ph +61 (8) 8259 6546
MOD/DSTO Fax +61 (8) 8259 5139
P.O. Box 1500 Email:
robert...@dsto.defence.gov.au
Salisbury, South Australia, 5108

Disclaimer: Opinions above are mine and may be worth what you paid for
them

Janice Allan

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
Hi Chris,

[snip]

>...I am confused as to whether interfaces


>are a 'workaround' for languages not providing multiple inheritance or
>truly a good thing.

I believe interfaces are a good thing; here's why.

Is a Cow a 'kind of' Animal or a 'kind of' Machine or a 'kind of'
FoodSource? Well the answer is all three depending on your point of view.
If you're a biologist then it's an Animal, if you're a farmer in a third
world country it's a Machine and if you're a meat eater then it's a
FoodSource. So when it comes to modelling this entity what are you going to
do, implement it three times - there's no such thing as tripple
inheritence - or are you going to implement it once and make it expose three
interfaces allowing the user to inherit the correct one depending on his
point of view. Sort of like subject orientated programming instead of
object orientated.

HTH,
Gary

Pentland Software Practice
Development and mentoring in C++ & Smalltalk
http://www.commercepark.co.uk/psp/


Jochen Bender

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
> I have a question about interfaces versus multiple inheritance.
> Recently I was 'bashed' on another listserver, when I suggested
> multiple inheritance is not such a bad idea (the programming language
> supports only single-inheritance).

You are not alone ;-)

> I was told in no uncertain terms that 'interfaces' are the way to go.

> Having done a bit of homework, I am confused as to whether interfaces


> are a 'workaround' for languages not providing multiple inheritance or
> truly a good thing.

I will try to make a point.
I like to use a certain type of inheritance a lot, that Bertrand Meyer
(Object-Oriented Software Construction, 2nd ed., a must-read), calls "facility
inheritance" (Off the top of my head -- I am not sure if I use the correct term
here, sorry).

A useful facility class might be a class COMPARABLE. COMPARABLE defines an
interface that comparable items must support in order to be -- well --
comparable. For simplicity, let's define COMPARABLE using only the three
(abstract) queries 'greater', 'smaller', 'equal', each returning a boolean
value.
Descendants can inherit from COMPARABLE, implement these methods and thus make
their objects comparable.
Now we can facilitate the descendant class designer's work by readily
implementing 'smaller': it can always return '(not greater) and (not equal)'.
(It's invariantly true that when 'a' is not greater than 'b', and 'a' and 'b'
are unequal, then 'a' must be smaller than 'b').

Another useful facility class might be STORABLE. STORABLE defines an interface
that items must support in order to be -- well -- storable to some file or
database. We'd most definitely neet the commands 'store' and 'retrieve' here.
Descendants can inherit from STORABLE, implement these methods and thus make
their objects storable.
We can facilitate the descendant class designer's work by readily providing an
ID mechanism, so that each storable object gets a unique ID when it's created.
The ID is stored with the object to identify it for later retrieval. All the ID
stuff will likely be the same for all STORABLE descendants.

So far, so good.
If I want to define some class so that its objects can both be compared to
another object *and* stored to a file, I simply inherit from both classes.

If STORABLE and COMPARABLE were only interfaces, we had to re-code the
'knowledge' readily implemented by STORABLE and COMPARABLE classes. Interfaces
have no knowledge.

In Delphi, to which you are most surely referring, and which I use, you are
restricted to single inheritance, so you are stuck with the following options
(Java is no different, as far as I know):
(1) Make COMPARABLE a class, STORABLE an interface.
Implement the COMPARABLE knowledge into the class, and let each descendant that
needs both facilities re-implement the entire logic that STORABLE items need.
Rock bottom.
(2) Make STORABLE a class, COMPARABLE an interface.
Implement the STORABLE knowledge into the class, and let each descendant that
needs both facilities re-implement the entire logic that COMPARABLE items need.

I won't discuss the option of declaring both as an interface, because that seems
least use of all.

Option (2) seems better, because the COMPARABLE facility is simpler (at the
moment) than the STORABLE facility.
But who knows about tomorrow?
And what if both facilities are rather complex?

I still prefer *true* multiple inheritance.


> The UML user guide describes 'interfaces' as a "collection of
> operations that are used to specify a service of a class or a
> component; every class may realise many interfaces" (p146)
>
> How does this fit in with the OO design principle that a class should
> provide a limited number of well defined services based on the
> underlying abstraction? Does it not encourage developers to design
> 'can-do-all' classes and simply use a number of 'interfaces' to group
> services together?

Not if the base classes (facility classes) represent proper, simple
abstractions. Then multiply-facility-inherited classes will still remain proper
and simple.

- Jochen

David Anderson

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
Gee! This is an interesting thread.

The best explanation of this is in "Java Design" by Peter Coad and Mark Mayfield. It shows you
why composition is a better strategy than inheritance and once you buy into that then Interfaces
is obviously the way to go.

Mohican of Mohawk wrote:

> i don't know if subject orientated programming as you
> are calling is, is good practice,

Yes, it is!

> it seeems that the Cow can play
> different Roles, or maybe not even so.

The Role Player pattern as I've heard it called is very powerful. It means that things don't
have to change class or can have behaviour added or taken away e.g.

A Banking system has a "user" who is a bank clerk. If that clerk applies for a loan then he is
also an "applicant". He may also have a deposit account so he is a "depositor". If you modelled
all that complexity with inheritance say starting with "Person" as the superclass then you would
soon get into trouble with masses of multiply inheriting sub-classes e.g. PersonUserApplicant,
PersonUserApplicantDepositor, PersonApplicant etc.. If you use composition and interfaces and no
inheritance then your "person" class can compose all the other roles. Roles can be added and
deleted as and when necessary and nothing ever has to change class. If you have a design where
things have to change class in order to continue to "be" then its a bad design.

Once you've finished reading "Java Design", get "Java Modeling" the next book from Peter Coad.
It will convince you beyond doubt that Role Player is a good strategy (pattern, if you prefer)

> Janice Allan <janice...@objectwon.u-net-com> wrote in message


>
> > I believe interfaces are a good thing; here's why.
> >
> > Is a Cow a 'kind of' Animal or a 'kind of' Machine or a 'kind of'
> > FoodSource? Well the answer is all three depending on your point of view.
> > If you're a biologist then it's an Animal, if you're a farmer in a third
> > world country it's a Machine and if you're a meat eater then it's a
> > FoodSource. So when it comes to modelling this entity what are you going
> to
> > do, implement it three times - there's no such thing as tripple
> > inheritence - or are you going to implement it once and make it expose
> three
> > interfaces allowing the user to inherit the correct one depending on his
> > point of view. Sort of like subject orientated programming instead of
> > object orientated.

A very good explanation.


Jeffrey L Straszheim

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
Janice Allan wrote:

> I believe interfaces are a good thing; here's why.

> Is a Cow a 'kind of' Animal or a 'kind of' Machine or a 'kind of'
> FoodSource? Well the answer is all three depending on your point of view.
> If you're a biologist then it's an Animal, if you're a farmer in a third
> world country it's a Machine and if you're a meat eater then it's a
> FoodSource. So when it comes to modelling this entity what are you going to
> do, implement it three times - there's no such thing as tripple
> inheritence - or are you going to implement it once and make it expose three
> interfaces allowing the user to inherit the correct one depending on his
> point of view. Sort of like subject orientated programming instead of
> object orientated.

This is all very interesting, but I see no connection between
your points and actual software engineering. Please describe
an application that would struggle between these models
of "cow" you are presenting.

--
--Jeffrey Straszheim
---Systems Engineer, Programmer
----stimuli AT shadow DOT net

Peter

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
In article <pT1P2.381$6C.4...@newsr2.u-net.net>, "Janice Allan"
<janice...@objectwon.u-net-com> wrote:

> I believe interfaces are a good thing; here's why.
>
> Is a Cow a 'kind of' Animal or a 'kind of' Machine or a 'kind of'
> FoodSource? Well the answer is all three depending on your point of view.
> If you're a biologist then it's an Animal, if you're a farmer in a third
> world country it's a Machine and if you're a meat eater then it's a
> FoodSource. So when it comes to modelling this entity what are you going to
> do, implement it three times - there's no such thing as tripple
> inheritence - or are you going to implement it once and make it expose three
> interfaces allowing the user to inherit the correct one depending on his
> point of view. Sort of like subject orientated programming instead of
> object orientated.

I don't think you understand multiple inheritance. With normal multiple
inheritance (inheritance of interface and implementation), you don't have
to provide an implementation. With interfaces, you have to reimplement.

Robert O'Dowd's post in this thread is excellent, by the way.

------------------------------------------------------------------------
p h i n e l y @hawaii.edu

Dylan... the high-performance dynamic language
* open-source Unix version: http://www.gwydiondylan.org/
* free Win32 version: http://www.harlequin.com/products/ads/dylan/
------------------------------------------------------------------------

Jeffrey L Straszheim

unread,
Apr 8, 1999, 3:00:00 AM4/8/99
to
David Anderson wrote:

> The best explanation of this is in "Java Design" by Peter Coad and Mark Mayfield. It shows you
> why composition is a better strategy than inheritance and once you buy into that then Interfaces
> is obviously the way to go.

In many cases they are, and every language I can think of that provides
multiple inheritance also provides interfaces. There are times, thoughs, when I
would like to bring some behavior in with the inheritance. Java doesn't allow
me to do this.

In a library I'm currently involved in, I have a class to represent a GUI window.
To create a window one needs a reference to a parent window, which is usually
simply another window, but sometimes can be the root window. In my system, the
root window cannot be modified by an application, so I don't model it using the WINDOW
class, instead I have a WINDOW_PARENT class. Also, I have a WINDOW_BASE class,
which abstracts the features that a child window must have. I abstract it out
as a separate class because some children might wish to delegate their implementation,
so I want to have a class with only those things a child needs. So, I have:

SCREEN
|
v
WINDOW_PARENT <----- \
+------ WINDOW
WINDOW_BASE <--------/

Becaue a window can be both a child and a parent. Now, a parent maintains a list
of children, as does any child (the parent may need to operate on grandchildren,
so needs access to them). So both WINDOW_PARENT and WINDOW_BASE inherit from a
common base WINDOW_COLLECTION (not shown above). WINDOW_COLLECTION includes
its implementation. As I am using Eiffel, this all works very easily with no
special work for me the programmer. With Java I just couldn't do this. I'd have
to present WINDOW_COLLECTION as an interface, then implement it in SCREEN and
WINDOW. Granted, the implementations could each delegate to some other class, but
I'd still have to write glue in each class that I'd rather not. If I add
more window classes I add more glue.

This is just one example. There is also the mixin style of programming.
What if, say, I implement a STREAMABLE class that provides features for
helping objects to write themselves onto a file stream. This is clearly
an "is a" relationship as I'd need a STREAMABLE interface so that I could
hand around streamable objects polymorphicly. But I'd also like to provide
some handy implementation features in STREAMABLE. With a pure interface
I can't do this: I must write all the routines of STREAMABLE myself, either
in full or with a separate delegated object and its protocols. I must
do this for each streamable class that I create. If I write one hundred
streamable classes I write the glue one hundred times.

> The Role Player pattern as I've heard it called is very powerful. It means that things don't
> have to change class or can have behaviour added or taken away e.g.

> A Banking system has a "user" who is a bank clerk. If that clerk applies for a loan then he is
> also an "applicant". He may also have a deposit account so he is a "depositor". If you modelled
> all that complexity with inheritance say starting with "Person" as the superclass then you would
> soon get into trouble with masses of multiply inheriting sub-classes e.g. PersonUserApplicant,
> PersonUserApplicantDepositor, PersonApplicant etc.. If you use composition and interfaces and no
> inheritance then your "person" class can compose all the other roles. Roles can be added and
> deleted as and when necessary and nothing ever has to change class. If you have a design where
> things have to change class in order to continue to "be" then its a bad design.

This is a good example of when not to use multiple inheritance. Java saves
you from ever having to choose.

I'd love to see an example of why having multiple inheritance hurts me?

Mohican of Mohawk

unread,
Apr 9, 1999, 3:00:00 AM4/9/99
to
i think one should just model a Cow as an Animal,
where an animal is a foodsource and a machine.
no inheritance needed, the public interfaces stay the same
cow.milk; is stiil avaialbable both, as an animal and as a food
source. i don't know if subject orientated programming as you
are calling is, is good practice, it seeems that the Cow can play
different Roles, or maybe not even so.


Mohican
[Cow.Suicide or Farmer.Slaughter(aCow)].
[Senior Developer IRIS International ]
[The Netherlands]


Janice Allan <janice...@objectwon.u-net-com> wrote in message

news:pT1P2.381$6C.4...@newsr2.u-net.net...
> Hi Chris,
>
> [snip]
>
> >...I am confused as to whether interfaces


> >are a 'workaround' for languages not providing multiple inheritance or
> >truly a good thing.
>

> I believe interfaces are a good thing; here's why.
>
> Is a Cow a 'kind of' Animal or a 'kind of' Machine or a 'kind of'
> FoodSource? Well the answer is all three depending on your point of view.
> If you're a biologist then it's an Animal, if you're a farmer in a third
> world country it's a Machine and if you're a meat eater then it's a
> FoodSource. So when it comes to modelling this entity what are you going
to
> do, implement it three times - there's no such thing as tripple
> inheritence - or are you going to implement it once and make it expose
three
> interfaces allowing the user to inherit the correct one depending on his
> point of view. Sort of like subject orientated programming instead of
> object orientated.
>

Jochen Bender

unread,
Apr 9, 1999, 3:00:00 AM4/9/99
to
> This is just one example. There is also the mixin style of programming.
> What if, say, I implement a STREAMABLE class that provides features for
> helping objects to write themselves onto a file stream. This is clearly
> an "is a" relationship as I'd need a STREAMABLE interface so that I could
> hand around streamable objects polymorphicly. But I'd also like to provide
> some handy implementation features in STREAMABLE. With a pure interface
> I can't do this: I must write all the routines of STREAMABLE myself, either
> in full or with a separate delegated object and its protocols. I must
> do this for each streamable class that I create. If I write one hundred
> streamable classes I write the glue one hundred times.

This is the killer argument, I think.
A STREAMABLE interface simply does not do the job. We need a STREAMABLE class.
100% agree.

- Jochen

Richard MacDonald

unread,
Apr 9, 1999, 3:00:00 AM4/9/99
to
Jochen Bender wrote in message <370DBE4C...@psplus.de>...
I agree too. However, multiple inheritance is not the only way.
Java-style interfaces confused me for a while -- "where does the
implementation go;
you mean I have to reimplement it ?!"
The pattern I use (in Smalltalk) is to create an Interface class and include
the implementation,
including single inheritance for all the varieties. Then, this class is
instantiated and "wraps"
around the "base" object.

Jeffrey L Straszheim

unread,
Apr 9, 1999, 3:00:00 AM4/9/99
to
Richard MacDonald wrote:

> I agree too. However, multiple inheritance is not the only way.
> Java-style interfaces confused me for a while -- "where does the
> implementation go;
> you mean I have to reimplement it ?!"
> The pattern I use (in Smalltalk) is to create an Interface class and include
> the implementation,
> including single inheritance for all the varieties. Then, this class is
> instantiated and "wraps"
> around the "base" object.

This works fine. I'm not saying Java is entirely bad or that you
can't make things work within it. However, many Java programmers
seem to respond to criticisms of their language's lack of MI by
responding that MI is somehow wrong or, at least, inconsequential.
I've programmed in Java, I liked it well enough, but I missed MI
a lot and like having it back (now that I'm using a language
that has it). It's one thing to say that one can by without MI, it
is quite another to say that one is better off without it. I have
yet to hear a good argument of the latter variety.

Dave Harris

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
nos...@nospam.com (Jeffrey L Straszheim) wrote:
> This works fine. I'm not saying Java is entirely bad or that you
> can't make things work within it. However, many Java programmers
> seem to respond to criticisms of their language's lack of MI by
> responding that MI is somehow wrong or, at least, inconsequential.
> I've programmed in Java, I liked it well enough, but I missed MI
> a lot and like having it back (now that I'm using a language
> that has it). It's one thing to say that one can by without MI, it
> is quite another to say that one is better off without it. I have
> yet to hear a good argument of the latter variety.

IMHO it's reasonable to argue that MI is not worth the cost. For example,
Eiffel has one of the better designs, but MI still adds a lot of language
complexity for programmers (eg feature joining, renaming, selection).

It also adds complexity for implementors. AIUI, all efficient Eiffel
implementations currently rely on whole-program analysis to deal with the
MI. Java's ambition is to support dynamic loading of classes efficiently,
and can't rely on such closed-world assumptions.

Dave Harris, Nottingham, UK | "Weave a circle round him thrice,
bran...@cix.co.uk | And close your eyes with holy dread,
| For he on honey dew hath fed
http://www.bhresearch.co.uk/ | And drunk the milk of Paradise."

Osvaldo Pinali Doederlein

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
Dave Harris <sc...@btinternet.com> wrote in message
news:memo.1999041...@btinternet.com...

> IMHO it's reasonable to argue that MI is not worth the cost. For example,
> Eiffel has one of the better designs, but MI still adds a lot of language
> complexity for programmers (eg feature joining, renaming, selection).

Compared to what?

Let's see the specific case of renaming because so many people complain
about that. Suppose I have base classes B1 and B2 and I want to add their
functionality, and their interfaces, to my new derived class D. In Eiffel,
D inherits both. But if there are signature clashes, I will be forced to
rename things. So what? There is no better solution AFAIK.

If I'm trying to do the same implementation e.g. in Smalltalk or Java, I can
only inherit one of B1 and B2. And this decision is sometimes random,
because my class may easily have an 'is-a' relationship with several
parents -- this happens all the time when you implement as classes "tags" as
Searchable, Comparable, Cloneable, Persistent, Remote and so on. Well, Java
solves the problem for interface but not for implementation, and ST is worse
(and would be really bad with static typing; I wonder how can you solve this
with static-typed SI languages). But in the implementation, some bases need
to use delegation. Does this fix the problem, in terms of design?

No, because I want D's clients to access functionality of B1 and B2 as if
they were D's. Now, implementation sucks because I need to write lots of
stubs to dispatch messages to my delegates, e.g.

D.m() {
b1_delegate.m();
}

...which is as bad as writing trivial accessors/mutators manually. And what
about interface clashes? The same problem of MI exists, because it may be
that B2 also defines a method m() and I want to expose it in D's interface.
All I need is chosing a different name in the stub:

D.m2() {
b2_delegate.m();
}

...and guess what, this is renaming as far as I can tell. It's only a
manual process, instead of a language-supported feature. Not being in the
language, we lose things like compiler checking and readability.

Finally, in some cases you _want_ to rename things even without clashes,
maybe to make your interface more specific. C++'s STL does that a lot in
its adaptor containers - so you have a stack which relies on other container
for all actuall implementation, but renames push_back() to push(), back() to
top() and pop_back() to pop(), so the user has more standard stack method
names. In this case too, explicit support for renaming in the language is
great, and manual implementation sucks.

> It also adds complexity for implementors. AIUI, all efficient Eiffel
> implementations currently rely on whole-program analysis to deal with the
> MI. Java's ambition is to support dynamic loading of classes efficiently,
> and can't rely on such closed-world assumptions.

I don't think MI is a particular big performance problem driving Eiffel
implementations. Java is not different because strong optimization always
depend on closed-world assumptions. Dynamic compilation can fix things when
new classes are loaded and break any assumptions, like monomorphic calls
becoming polymorphic. And native compilers for Java impose some management
to dynamic loading, either by requiring the programmer to specifiy at
compile time all classes that can be loaded, or by having mixed
architectures.

Peter

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to
In article <370E7B67...@nospam.com>, Jeffrey L Straszheim
<nos...@nospam.com> wrote:

> This works fine. I'm not saying Java is entirely bad or that you
> can't make things work within it. However, many Java programmers
> seem to respond to criticisms of their language's lack of MI by
> responding that MI is somehow wrong or, at least, inconsequential.
> I've programmed in Java, I liked it well enough, but I missed MI
> a lot and like having it back (now that I'm using a language
> that has it). It's one thing to say that one can by without MI, it
> is quite another to say that one is better off without it. I have
> yet to hear a good argument of the latter variety.

Here are some real world numbers:

Library Language Classes MaxDepth Parents Ancestors
max/avg max/avg
GEO Eiffel 1319 14 16/1.89 50/14


Note that each class in this Eiffel library has on average almost two parents!

This is from the paper: "Efficient Type Inclusion Tests", Vitek, et.
al. OOPSLA, 97

There are more figures for other libraries and languages, but I am too
lazy to type them in.

Peter

unread,
Apr 10, 1999, 3:00:00 AM4/10/99
to

> IMHO it's reasonable to argue that MI is not worth the cost. For example,
> Eiffel has one of the better designs, but MI still adds a lot of language
> complexity for programmers (eg feature joining, renaming, selection).

But nonetheless, multiple inheritance seems to be used extensively in
Eiffel, at least in some libraries. See my previous post with real-world
numbers from a large Eiffel library.

Ed Falis

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
On Sat, 10 Apr 1999 11:29:47 -1000, phXi...@haXwaii.eXdu (Peter) wrote:
> In article <370E7B67...@nospam.com>, Jeffrey L Straszheim
> <nos...@nospam.com> wrote:
>
> > It's one thing to say that one can by without MI, it
> > is quite another to say that one is better off without it. I have
> > yet to hear a good argument of the latter variety.
>
> Here are some real world numbers:
>
> Library Language Classes MaxDepth Parents Ancestors
> max/avg max/avg
> GEO Eiffel 1319 14 16/1.89 50/14
>
>
> Note that each class in this Eiffel library has on average almost two parents!
>

It's not clear to me what these figures are supposed to demonstrate relative to the question. Eiffel applications lean towards extensive use of MI as a natural way to
do mixins and roles, so I personally don't find an average of two parents to be horrifying, if that's the intent of the figures (count the average combined number of
parent + interfaces implemented in a Java system as a perhaps comparable figure). Is that what you were getting at?

- Ed Falis

Dave Harris

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
osv...@visionnaire.com.br (Osvaldo Pinali Doederlein) wrote:
> Suppose I have base classes B1 and B2...

If you need it, you need it. MI is one of those many language features
which are sometimes so essential that if the language doesn't support it
directly you have to simulate it by hand. Garbage collection and mutating
classes on the fly are other examples. Simulating it by hand is generally
less good than having it built in.

It doesn't follow that every language should have everything built in.
There are costs and trade-offs involved. This is especially sensitive for
things which incur costs even for code which doesn't use them. So there is
a judgement call. With its interfaces, Java has found an interesting
trade-off point. It works for a great many programs.


> I don't think MI is a particular big performance problem driving Eiffel
> implementations. Java is not different because strong optimization
> always depend on closed-world assumptions. Dynamic compilation can
> fix things when new classes are loaded and break any assumptions,
> like monomorphic calls becoming polymorphic. And native compilers
> for Java impose some management to dynamic loading, either by
> requiring the programmer to specifiy at compile time all classes
> that can be loaded, or by having mixed architectures.

It's surprising what is possible even in a dynamic environment. However,
it's a difficult and subtle area. To me it seems that not having true MI
makes dynamic compilation significantly easier. At least you know your
instance variables aren't going to move about.

Jeffrey L Straszheim

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
Dave Harris wrote:

> IMHO it's reasonable to argue that MI is not worth the cost. For example,
> Eiffel has one of the better designs, but MI still adds a lot of language
> complexity for programmers (eg feature joining, renaming, selection).

Fair enough. I find the added complexity easy to deal with though.
Most of the time you really don't need the more complex inheritance
tools, and when you do nothing else would quite do the job.



> It also adds complexity for implementors. AIUI, all efficient Eiffel
> implementations currently rely on whole-program analysis to deal with the
> MI. Java's ambition is to support dynamic loading of classes efficiently,
> and can't rely on such closed-world assumptions.

This is an interesting point. It suggests the real possibility that
MI might simply not be right for Java, given the overall design goals
of Java. I'm not a language designer, and I'm not sure if the dynamic
loading of classes should really preclude the use of MI, but I can see
that, as a whole, leaving MI out will leave a smaller, simpler language;
minimizing reliance of system wide analysis will leave the ability to
be far more dynamic in your runtime inclusion of classes. That being said,
is Java the right language for me, and is it the best choice for large
scale, mission critical systems? After all, it has been the claim of Java
supporters that their language is not simply for cool-web-gizmos. Could
it be that Java has a valid niche, but for systems on the smallish scale?

Another interesting question you've raised is whether there is a "right"
scale for dynamic inclusion. That is, Java allows the dynamic loading of
classes at the cost of limited system analysis. It turns out that Eiffel's
system analysis allows for some really powerful optimization. For instance,
consider a library class, say STRING, that contains dozens of complex methods.
With traditional languages, and certainly with Java, if you include such a
class in your program you cannot but include it's entirety. For some classes
this might be quite a lot of code. With Eiffel, however, the compiler can
figure out just those methods actually called by your system and only include
those. Also, there is the intelligent treatment of dynamic binding; the
compiler can figure out when and how to use the various binding algorithms.
Now, this scheme alone ignores the real need for some form of dynamic linking.
Small Eiffel, for instance, gives you very little support for anything
other than building monolithic programs--it does that well, but only that.
Some folks are working on Cobra support and such, but that is still on its
way. ISE Eiffel does have COM support, proving that Eiffel can give support
for dynamic loading, but this is on the component scale and not on the class
scale.

Now here's my question: for applications on a typical to largish scale, is
there any real need for the dynamic loading of individual classes? Is the
dynamic loading of components sufficient, or (as I suspect) superior?

Peter

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
In article <1103_923789710@DZOG-CHEN>, fa...@ma.aonix.com (Ed Falis) wrote:

> On Sat, 10 Apr 1999 11:29:47 -1000, phXi...@haXwaii.eXdu (Peter) wrote:
> > In article <370E7B67...@nospam.com>, Jeffrey L Straszheim
> > <nos...@nospam.com> wrote:
> >
> > > It's one thing to say that one can by without MI, it
> > > is quite another to say that one is better off without it. I have
> > > yet to hear a good argument of the latter variety.
> >
> > Here are some real world numbers:
> >
> > Library Language Classes MaxDepth Parents Ancestors
> > max/avg max/avg
> > GEO Eiffel 1319 14 16/1.89 50/14
> >
> >
> > Note that each class in this Eiffel library has on average almost two
parents!
> >
>
> It's not clear to me what these figures are supposed to demonstrate relative
> to the question.

It demonstrates that multiple inheritance is used extensively in some real
world cases, and therefore is possibly a valuable modeling tool (one which
shouldn't be discarded without serious thought.)

>Eiffel applications lean towards extensive use of MI as a natural way to
> do mixins and roles, so I personally don't find an average of two
parents to be
> horrifying,

I don't find it horrifying either, and wasn't meaning to imply that.

> if that's the intent of the figures (count the average combined number of
> parent + interfaces implemented in a Java system as a perhaps comparable
figure).
> Is that what you were getting at?
>

Actually, the use of interfaces seems to be relatively rare in the Java
JDK 1.02 library:

Language Library Types MaxDepth Parents Ancestors
max/avg max/avg
Eiffel GEO 1319 14 16/1.89 50/14
Java JDK1.02 225 7 3/1.04 7/3.43
^^^^

This data is again from the Vitek paper.

Ed Falis

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
On Sun, 11 Apr 1999 10:52:51 -1000, phXi...@haXwaii.eXdu (Peter) wrote:

> It demonstrates that multiple inheritance is used extensively in some real
> world cases, and therefore is possibly a valuable modeling tool (one which
> shouldn't be discarded without serious thought.)
>

My apology - I read the intent of your msg incorrectly.

- Ed

Peter

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
In article <3710A219...@nospam.com>, Jeffrey L Straszheim
<nos...@nospam.com> wrote:

> Could it be that Java has a valid niche, but for systems on
> the smallish scale?

For an example of Java not scaling well to a complex system, you might
want to look at Harlequin's paper titled "COM Simplified: Modern Languages
& Microsoft's Component Object Model" at
http://www.harlequin.com/products/ads/dylan/com/

Harlequin of course sells an implementation of the Dylan programming
language, but it doesn't invalidate the points in the paper that Java and
C++ leave much to be desired in managing the complexity of Microsoft's
COM. Microsoft had to extend the Java language itself to make COM useable
from Java.

Dave Harris

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
nos...@nospam.com (Jeffrey L Straszheim) wrote:
> Could it be that Java has a valid niche, but for systems on the
> smallish scale?

The implicit argument here is that languages for large scale systems must
have multiple inheritance. I don't think that's proven. It would also rule
out Smalltalk, for instance. Admittedly MI isn't so necessary for
Smalltalk because that language is dynamically typed; on the other hand,
as far as static typing goes Java does have MI in the form of interfaces.
(This is a fairly deep and subtle point.)

However, Java is also lacking direct support for many other features, eg
genericity, design by contract, delegation and operator overloading. These
may kill it for large scale development even if full MI were added.


> Now here's my question: for applications on a typical to largish scale,
> is there any real need for the dynamic loading of individual classes?
> Is the dynamic loading of components sufficient, or (as I suspect)
> superior?

First let's be clear that we're moving towards a new paradigm here.
Monolithic executables have been fine in the past, and what has worked
will surely continue to work. Java is trying to explore a new style, based
around mobile code, agents, heterogenous networks, JINI, "the network is
the computer", intelligent toasters, wearable computers and all the rest.
I think it's too early to say whether this stuff will pan out, whether it
will work but remain just a niche or whether it will become mainstream.

It *could* become mainstream. To take your example of linking in only
required methods from the String library class... a future system that ran
an application over a network could make that decision at run time.
Instead of downloading every String method that the app might use if every
execution path is followed, just fetch the ones it does use in the paths
that *are* followed. Or the ones it used last time, or whatever clever
caching you can think of. This could reduce bandwidth. So some of the
background assumptions that lie behind your String example may get
challenged. Some decisions are best postponed until runtime.

Secondly, we're only talking about efficiency. No-one is saying MI can't
be done in a Java-like system, just that it might be relatively slow.
Indeed there are projects that aim to compile Eiffel into Java bytecodes.
If MI is truly as important as the Eiffel guys think, and if dynamic
linking is as important as the Java guys think, then put them together and
accept the speed hit. It'll be worth it.

Which isn't to say Java should have had MI from the beginning. It's
difficult to get a new language established. Speed is one of the most
common objections people had to using Java. Arguably the language could
not have afforded another speed hit early in its life. Now, however, it is
pretty well established. It is also much faster as JITs have replaced
interpreters. Maybe now Java can squander some of that speed and goodwill
on MI when it couldn't have afforded the risk before.

Thirdly, you seem to be saying that efficiency doesn't matter across
component boundaries. You want good optimisation within components but
don't care if the external interfaces are slow. Because if dynamic linking
does not bring an efficiency hit, how can static linking possibly be
superior?

We are seeing a trend towards greater use of components in the mainstream,
with COM, SOM, CORBA and the like. Of course they don't *have* to be
fine-grained, but I think it could be beneficial. Many of the benefits of
components apply even when the components are small. We are stuck with big
components mainly *because* we are limited by efficiency across the
boundaries. You're trying to turn a necessity into a virtue there.

The Java ambition is for dynamic linking to be fast enough to use for
everything. The trick is to make it efficient without otherwise
compromising good design. This is an active research area.

I've picked up on MI as something I believe is hard, but don't let that
blind you to how much has been done elsewhere. Read the papers on
Smalltalk, Self and HotSpot. They can replace dynamic dispatch with
static, and the static with inlining, even across dynamic boundaries. They
can back out of optimisations if a subsequently loaded class invalidates a
previous assumption. We can hope that the state of the art will advance to
where MI can be dealt with.

Dave Harris

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
phXi...@haXwaii.eXdu (Peter) wrote:
> But nonetheless, multiple inheritance seems to be used extensively in
> Eiffel, at least in some libraries.

Yes. People sometimes argue that complex language features don't matter
because most programmer need never see them. That's not true here. You
won't get very far in Eiffel without encountering multiple inheritance.

On the other hand, there are far worse things in other languages. Java
doesn't really strike me as "simple" even without MI.

Jeffrey L Straszheim

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
Peter wrote:

> For an example of Java not scaling well to a complex system, you might
> want to look at Harlequin's paper titled "COM Simplified: Modern Languages
> & Microsoft's Component Object Model" at
> http://www.harlequin.com/products/ads/dylan/com/

I have just read the article, but I don't think it is a fair example
of how Java fails to scale. More so, it is an example of how lousy
COM is for anything other than Visual Basic or Visual C++. Java provides
a rather strict layer between its code and the underlying libraries of
the machine it runs on. This was, of course, designed into the language
and is quite justified considering the environments it is expected to
run in.

This being so, and given that COM and Java did not grow up together
(the way VB and COM did) and given that the underlying RPC/IDL tools
of C/C++ are not directly available to Java, that it is difficult to
give a "pretty" interface to COM within Java seems more a problem with
COM than Java. The Java RMI library is proof that Java can support COM
like functionallity within itself.

I should say that I do expect that Java will fail to scale, but not for
that reason.

Jeffrey L Straszheim

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
Dave Harris wrote:

> The implicit argument here is that languages for large scale systems must
> have multiple inheritance. I don't think that's proven. It would also rule
> out Smalltalk, for instance. Admittedly MI isn't so necessary for
> Smalltalk because that language is dynamically typed; on the other hand,
> as far as static typing goes Java does have MI in the form of interfaces.
> (This is a fairly deep and subtle point.)

Actually, that wasn't my point. I think that Java the Language (which
is specifically separate from the JVM) will not scale well in its present
for for a variety of reasons that I didn't spell out (after all, they are
well covered on groups such as this). I do think that a very flexible
inheritance mechanism is a huge benifit when integrating code from a
variety of libraries, and that MI would probably be included in any
"very flexible" inheritance mechanims. But of course, I haven't seen
every inheritence mechanism so I expect that there will be developments
in the future that will quite eclipse my present assumptions. I can
say, however, that Java isn't among such developments.



> However, Java is also lacking direct support for many other features, eg
> genericity, design by contract, delegation and operator overloading. These
> may kill it for large scale development even if full MI were added.

My point exactly :)



> First let's be clear that we're moving towards a new paradigm here.
> Monolithic executables have been fine in the past, and what has worked
> will surely continue to work. Java is trying to explore a new style, based
> around mobile code, agents, heterogenous networks, JINI, "the network is
> the computer", intelligent toasters, wearable computers and all the rest.
> I think it's too early to say whether this stuff will pan out, whether it
> will work but remain just a niche or whether it will become mainstream.

> It *could* become mainstream. To take your example of linking in only
> required methods from the String library class... a future system that ran
> an application over a network could make that decision at run time.
> Instead of downloading every String method that the app might use if every
> execution path is followed, just fetch the ones it does use in the paths
> that *are* followed. Or the ones it used last time, or whatever clever
> caching you can think of. This could reduce bandwidth. So some of the
> background assumptions that lie behind your String example may get
> challenged. Some decisions are best postponed until runtime.

This is all possible. Call me conservative I guess, but I am thinking
along the lines of systems such as the Air Traffic Control Network or
a state Motor Department of Motor Vehicles information system. I don't
know if "wearable computers" or "intelligent toasters" really are the model
here. Of course, perhaps we could have something rather like Eiffel running
on the backend and something rather like Java running on a little hand held
unit that an inspection officer holds. Many possibilities come to mind.

<snip>



> Thirdly, you seem to be saying that efficiency doesn't matter across
> component boundaries. You want good optimisation within components but
> don't care if the external interfaces are slow. Because if dynamic linking
> does not bring an efficiency hit, how can static linking possibly be
> superior?

> We are seeing a trend towards greater use of components in the mainstream,
> with COM, SOM, CORBA and the like. Of course they don't *have* to be
> fine-grained, but I think it could be beneficial. Many of the benefits of
> components apply even when the components are small. We are stuck with big
> components mainly *because* we are limited by efficiency across the
> boundaries. You're trying to turn a necessity into a virtue there.

This is exactly the question I'm raising: should components be large
or small? My own thinking is that largish components will lead to
more reusability and simpler designs. Perhaps I'll prove wrong on this,
but I haven't seen evidence yet. I'd love to hear your ideas.

<snip>

Thank you :)

Jeffrey L Straszheim

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
Ell wrote:

> Ahhh, please for what reason(s) then?

In short: the lack of generics, the lack of sophisticated inheritance
mechanisms, a clumsy syntax, poor symmetry between reference types and
"built in" types, automatic documentation tools that do nothing but
format comments and do not analyze real syntax (e.g. javadoc vs. short),
and no genuine support for assersion mechanisms. Also, as a lesser
criticism, I find the various "standard" libraries rather clumsy,
although this could be fixed.

Please note after you have read this list that I have used Java, so
these are not mere abstract criticisms that I am quoting from other
liturature (although, indeed they all do appear in other liturature).
They are all aspects of Java that I missed while using it and greatly
appriciate when using a language that supports them.

Do these all imply that Java will fail to scale? Time will tell.
Certainly, very large projects have been managed in languages that
most will agree shouldn't scale well (C comes to mind), so
there will be large projects in Java that do succeed.

One test I suggest is how easily will Java allow you to integrate,
within one project, code from two different (but orthogonal) libraries.
Say the project, since we are talking about scaling, itself involves
a few hundred classes. Only a real world case study will tell us
anything--does anyone on this newsgroup know of a reference?

Peter

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
In article <memo.19990411...@btinternet.com>, bran...@cix.co.uk
wrote:

> Which isn't to say Java should have had MI from the beginning. It's
> difficult to get a new language established. Speed is one of the most
> common objections people had to using Java. Arguably the language could
> not have afforded another speed hit early in its life. Now, however, it is
> pretty well established. It is also much faster as JITs have replaced
> interpreters. Maybe now Java can squander some of that speed and goodwill
> on MI when it couldn't have afforded the risk before.

As far as I know, multiple inheritance does not present significant
performance problems. The speed hit is minimal.

Peter

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
In article <37112CE9...@nospam.com>, Jeffrey L Straszheim
<nos...@nospam.com> wrote:

> Peter wrote:
>
> > For an example of Java not scaling well to a complex system, you might
> > want to look at Harlequin's paper titled "COM Simplified: Modern Languages
> > & Microsoft's Component Object Model" at
> > http://www.harlequin.com/products/ads/dylan/com/
>
> I have just read the article, but I don't think it is a fair example
> of how Java fails to scale. More so, it is an example of how lousy
> COM is for anything other than Visual Basic or Visual C++. Java provides
> a rather strict layer between its code and the underlying libraries of
> the machine it runs on.

COM is certainly ugly, but with a decent macro system, one can make it
not-so-ugly to use. I think that is the main point of the paper. A
language such as Dylan is extensible through its hygienic macro system.
Java and C++ are not self-extensible. Microsoft had to extend the Java
language in their own vendor-specific way in order to make the interface
to COM pretty.

To quote from the paper:
This paper describes three contrasting approaches.

Extension using code generation. This approach
uses software tools such as wizards to generate
code which implements the connection between COM
and the application code. Visual C++ uses this
methodology.

Extension using hard-wired language changes. This
approach integrates COM semantics into the
language in a vendor-supplied non-extensible way.
Visual J++ uses this method.

Extension using dynamic language features. This
approach integrates COM semantics into the
language by extending the language in a
customizable and layered fashion; the extensions
are created using standard language features.
Dylan uses this method.

Mark Hathaway

unread,
Apr 11, 1999, 3:00:00 AM4/11/99
to
> In article <pT1P2.381$6C.4...@newsr2.u-net.net>,
> "Janice Allan" <janice...@objectwon.u-net-com> wrote:
>
> Hi Chris,
>
[snip]
>

>> someone wrote:
>>
>>...I am confused as to whether interfaces are a 'workaround' for
>> languages not providing multiple inheritance or truly a good thing.

> Is a Cow a 'kind of' Animal or a 'kind of' Machine or a 'kind of'


> FoodSource? Well the answer is all three depending on your point of view.

>...


> So when it comes to modelling this entity what are you going to

> do, implement it three times - there's no such thing as triple


> inheritence - or are you going to implement it once and make it expose three
> interfaces allowing the user to inherit the correct one depending on his
> point of view. Sort of like subject orientated programming instead of
>object orientated.

One implements a cow as a cow is. What you're describing falls more into
the category of how one object relates to another. In real life you may have
a farmer using a cow to pull a plow or a man killing a cow to make burgers,
but there are two actors involved: man & cow. The cow doesn't harness itself
to the plow. The cow doesn't kill itself and grind itself up. How does one
model the real life "objects"? One models each and every one which is
necessary to represent the slice of life one needs for the software. How
a language allows one to relate the objects is more to the point.

How does Dylan, Sather, C++, Smalltalk or other OO languages allow objects
to relate?

Ell

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
Jeffrey L Straszheim <nos...@nospam.com> wrote:

#I should say that I do expect that Java will fail to scale, but not for
#that reason.

Ahhh, please for what reason(s) then?

Elliott
--
:=***=: Objective * Holistic * Overall pre-code Modelling :=***=:
Hallmarks of the best SW Engineering
study Craftite vs. Full Blown OO: http://www.access.digex.net/~ell
copyright 1999 Elliott. exclusive of others' writing. may be copied freely
only in comp., phil., sci. usenet & bitnet & otug.

Robert O'Dowd

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
David Anderson wrote:
>
> Gee! This is an interesting thread.

>
> The best explanation of this is in "Java Design" by Peter Coad and Mark Mayfield. It shows you
> why composition is a better strategy than inheritance and once you buy into that then Interfaces
> is obviously the way to go.
>

That really depends on what you mean by better. As with anything in
modelling and design,
there are trade-offs between using inheritence or composition. As to
which is better, that
depends on your requirement. Functionally, there is very little you can
achieve
with either scheme that you can't achieve with the other. The amount of
effort
varies, however. Some things are easier with inheritence, others with
aggregation.

Inheritence (of the form B inherits from A) can be modelled equally in
the form
of "B contains one A". Inheritence gives the ability for class B to
inherit
behaviour and interfaces from class A, and selectively override some of
that
inherited behaviour. With aggregation, the same sort of thing can only
be
achieved if class B provides a relevant interface that delegates
operations
to the contained A --- so inheritence of interfaces is relevant IF
aggregation
is the most sensible choice.

Inheritence is often implemented --- behind the scenes of a compiler ---
by
aggregation. That is fine; the compiler does the work of implementing
the
interface. However, the effort involved with a human using aggregation
to
model the same thing --- and manually providing the relevant interface
--- often
exceeds the effort to do it with simple inheritence. Yes, it is
possible to do
any inheritence scheme with interfaces and aggregation. That does NOT
mean
this is always the best approach --- it simply means it is necessary to
decide what your requirements are and pick the tool best suited to the
job.

Keep in mind, when reading books on Java, that Java does not support
multiple
inheritence, other than inheritence of multiple interfaces. This means
the
only way a Java programmer can get anything comparable to multiple
inheritence
is by aggregation and use of interfaces. So, for a Java programmer,
this is
(probably rightly) the recommended option. It is, however, a constraint
forced by the language rather than a particular design method.

-<Automagically included trailer>
Robert O'Dowd Ph +61 (8) 8259 6546
MOD/DSTO Fax +61 (8) 8259 5139
P.O. Box 1500 Email:
robert...@dsto.defence.gov.au
Salisbury, South Australia, 5108

Disclaimer: Opinions above are mine and may be worth what you paid for
them

Osvaldo Pinali Doederlein

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
Hi,

Peter <phXi...@haXwaii.eXdu> wrote in message
news:phXinXely-110...@usrns41.dialup.hawaii.edu...


> COM is certainly ugly, but with a decent macro system, one can make it
> not-so-ugly to use. I think that is the main point of the paper. A
> language such as Dylan is extensible through its hygienic macro system.
> Java and C++ are not self-extensible. Microsoft had to extend the Java
> language in their own vendor-specific way in order to make the interface
> to COM pretty.

The CORBA mapping for Java is "pretty" and it needs no macros. Other things
do suck because C++ is ugly, or because COM is ugly, or both :)

Dave Harris

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
phXi...@haXwaii.eXdu (Peter) wrote:
> As far as I know, multiple inheritance does not present significant
> performance problems. The speed hit is minimal.

Are you thinking here of technology in Dylan? I don't know it well enough
to comment. Do you know Java well enough to say whether the Dylan approach
could have been useful for that language? Without losing the ability to
load new classes on the fly at any time? The issue is about the extent to
which systems like Dylan and Eiffel get their speed from a static, whole
program analysis which is not possible in Java.

A lot of JVM implementations make calling an interface method slower than
calling a class method. I don't know if they all do, or if its necessary
that they do. If not, it would be an example of the technology maturing.

Charles R. Martin

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
sc...@btinternet.com (Dave Harris) writes:

.. nos...@nospam.com (Jeffrey L Straszheim) wrote:
.. > This works fine. I'm not saying Java is entirely bad or that you
.. > can't make things work within it. However, many Java programmers
.. > seem to respond to criticisms of their language's lack of MI by
.. > responding that MI is somehow wrong or, at least, inconsequential.
.. > I've programmed in Java, I liked it well enough, but I missed MI
.. > a lot and like having it back (now that I'm using a language
.. > that has it). It's one thing to say that one can by without MI, it
.. > is quite another to say that one is better off without it. I have
.. > yet to hear a good argument of the latter variety.
..
.. IMHO it's reasonable to argue that MI is not worth the cost. For example,
.. Eiffel has one of the better designs, but MI still adds a lot of language
.. complexity for programmers (eg feature joining, renaming, selection).
..
.. It also adds complexity for implementors. AIUI, all efficient Eiffel
.. implementations currently rely on whole-program analysis to deal with the
.. MI. Java's ambition is to support dynamic loading of classes efficiently,
.. and can't rely on such closed-world assumptions.
..


I agree that MI is harder to deal with respopnsibly and in ways that
assure correctness, but (after waffling for some years about it) I've
concluded that I really do think MI is useful. The primary reason is
that the utility of mixin's is just too great.

Java interfaces were an attempt to provide something like mixin's
without buying into the other complexities of MI, and it works out
pretty well IMHO -- but I still miss being able to multiply inherit
BEHAVIOR as well as just a contract to PROVIDE behavior.
--
Gegen Dummheit kämpfen die Götter selbst vergäbens.
-- Schiller
* Charles R. Martin * Sun Java Center (Denver) * x75109 * 303 272 5109 *

Peter

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
In article <memo.19990412...@btinternet.com>, bran...@cix.co.uk
wrote:

> phXi...@haXwaii.eXdu (Peter) wrote:
> > As far as I know, multiple inheritance does not present significant
> > performance problems. The speed hit is minimal.
>
> Are you thinking here of technology in Dylan? I don't know it well enough
> to comment.

I was not thinking of any particular language. I am not an expert in
this area, and have never implemented inheritance in a language. I base
my assertion on what I have read in journal papers on the costs of dynamic
dispatch.

If I remember correctly, a virtual function call in C++ takes about 6
machine instructions. Multiple inheritance adds a few more instructions I
think, but only when it's being used.

Dave Harris

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
nos...@nospam.com (Jeffrey L Straszheim) wrote:
> This is all possible. Call me conservative I guess, but I am thinking
> along the lines of systems such as the Air Traffic Control Network or
> a state Motor Department of Motor Vehicles information system. I don't
> know if "wearable computers" or "intelligent toasters" really are the
> model here. Of course, perhaps we could have something rather
> like Eiffel running on the backend and something rather like
> Java running on a little hand held unit that an inspection
> officer holds. Many possibilities come to mind.

I guess it is a question of where you can benefit from breaking the
"closed world" assumption. In the Air Traffic case, maybe it would be
useful if the objects that represented specific aircraft were actually
stored in the aircraft, and downloaded to the ATC system dynamically.

Maybe if we think of ad hoc database queries as being software agents then
the "mobile code" approach fits there, too. AIUI that is what sometimes
what happens today, with SQL being the query language instead of Java.
Different language, same paradigm, already adopted.

That said, those are conservative areas. In the ATC case they shouldn't
touch agents with a barge pole until they've had several decades worth of
proving. In the database case, they already have highly tuned,
near-optimal solutions. I said before, "Monolithic executables have been
fine in the past, and what has worked will surely continue to work." I
neant it.


> This is exactly the question I'm raising: should components be large
> or small? My own thinking is that largish components will lead to
> more reusability and simpler designs.

What's your reasoning? Why would you want a lower limit on the size of
components? What is it that stops them being useful?

For example... applications are becoming more customisable, more
configurable. At some point that involves programming, and so we have
myriads of scripting languages. If an app is written in Java, and uses the
Command pattern, it seems fairly natural to have components that are
Command subclasses implemented in Java and loaded on the fly.

Jeffrey L Straszheim

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
Dave Harris wrote:

[snip discussion concerning the ideal size of components]



> What's your reasoning? Why would you want a lower limit on the size of
> components? What is it that stops them being useful?

> For example... applications are becoming more customisable, more
> configurable. At some point that involves programming, and so we have
> myriads of scripting languages. If an app is written in Java, and uses the
> Command pattern, it seems fairly natural to have components that are
> Command subclasses implemented in Java and loaded on the fly.

Well, I'm thinking on the level of useful interfaces here. I can easily
see a standardized spell-check interface that would allow folks to mix
and match their spell checkers and their various text processing tools.
All that is required is that the folks who make spell checking tools
come to some agreement with the folks who make text processing software.

But to mix and match a command such as "select all" is, I think, not
possible. Different sorts of data objects will need to respond to a user
request "select all" in a rather individual manner, and the code for this
would be built into the specific data component.

So, the command objects would likely be closely tied to the data object
in question, at least for the example as I'm envisioning it. The model
you seem to be suggesting would involve the client of the data component
instantiating specific command objects and sending them to the data object.
I think that this could just as easily be achieved by clients calling methods
on the data object. If, internally, the data components choose to use
an implementation using command objects (for instance, to support Undo)
it could, but the client need not trouble himself with such.

I guess both designs could be useful in one circumstance or another. I
tend to think that components are best built using some sort of facade
pattern and on the scale of "spell checker" or "graphics image". This
seems easier for a client to use and reuse.

However, all that being said, many of the COM interfaces have proven
quite useful even though some objects seem rather on the same scale
as a traditional OOPL class--IStorage and friends come to mind. Perhaps
I just need to think about this more.

<The author at this point thinks some more>

I guess my thinking is that, as a client of some component package, I
don't really want to see aspects of that package that I can't directly
use and reuse. If the only thing I can do with a command object is send
it to a specific class of data objects, then they may as well be hidden
within those data objects, which can then expose an interface to me.

Of course, if we add real (as in working transparently within the language)
object persistence and network transparency to the "sending" of an object,
then exposing the command objects makes more sense.

Now the question remains: what do I gain by putting each command in
its own .class file instead of having the whole package in one DLL?
Furthermore, the structure I mentioned above seems complex enough that
I doubt I could mix and match it at run time with another from a
different vendor; so, what do I gain by having it a "component" instead
of simply compiling it into my program? For instance, if Microsoft had
simply implemented their IStorage protocols as a basic DLL and provided
decent wrappers for the major languages (e.g. VB, C++ etc.), what would
have been lost? Binary compatibility is one thing, as it stands any
language that supports COM can use IStorage with no extra effort. Will
this same benifit be achieved for .class files?

Joachim Durchholz

unread,
Apr 12, 1999, 3:00:00 AM4/12/99
to
Jeffrey L Straszheim wrote:
>
> This is an interesting point. It suggests the real possibility that
> MI might simply not be right for Java, given the overall design goals
> of Java. I'm not a language designer, and I'm not sure if the dynamic
> loading of classes should really preclude the use of MI,

Dynamic class loading does not preclude MI. Eiffel both uses and needs
system-wide analysis, but for reasons that are unrelated to MI. It does
uses system-wide analysis to optimize some MI-related issues though -
the mechanism is there, so it gets used for MI as well.

A simple way to integrate MI into a dynamically-loaded environment would
be an additional indirection for each subroutine call and for each
attribute access. Given that Java on a JVM isn't very fast anyway, this
might even have been an option. (And JIT compilation could do some
limited form of system analysis to make the stuff zip along - not only
to make MI fast but to do type inference and inlining as well.)

Regards,
Joachim
--
Please don't send unsolicited ads.


Robert O'Dowd

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
Charles R. Martin wrote:
>
> sc...@btinternet.com (Dave Harris) writes:
>
> .. nos...@nospam.com (Jeffrey L Straszheim) wrote:
> .. > This works fine. I'm not saying Java is entirely bad or that you
> .. > can't make things work within it. However, many Java programmers
> .. > seem to respond to criticisms of their language's lack of MI by
> .. > responding that MI is somehow wrong or, at least, inconsequential.
> .. > I've programmed in Java, I liked it well enough, but I missed MI
> .. > a lot and like having it back (now that I'm using a language
> .. > that has it). It's one thing to say that one can by without MI, it
> .. > is quite another to say that one is better off without it. I have
> .. > yet to hear a good argument of the latter variety.
> ..
> .. IMHO it's reasonable to argue that MI is not worth the cost. For example,
> .. Eiffel has one of the better designs, but MI still adds a lot of language
> .. complexity for programmers (eg feature joining, renaming, selection).

Cost to who? The language designers who must define how it is done?
The
compiler writers who must implement it? Or the programmers who use the
language?
Yes, MI can result in unnecessarily complex software. It also gives a
tool
for programmers to model (and implement) complex systems. Workarounds
for
MI (eg aggregation combined with interfaces) are possible but they do,
in
turn, eventually introduce different types of complexity (e.g. keeping
track of multiple implementations of a given interface).

> ..
> .. It also adds complexity for implementors. AIUI, all efficient Eiffel
> .. implementations currently rely on whole-program analysis to deal with the
> .. MI. Java's ambition is to support dynamic loading of classes efficiently,
> .. and can't rely on such closed-world assumptions.
> ..
>
> I agree that MI is harder to deal with respopnsibly and in ways that
> assure correctness, but (after waffling for some years about it) I've
> concluded that I really do think MI is useful. The primary reason is
> that the utility of mixin's is just too great.
>
> Java interfaces were an attempt to provide something like mixin's
> without buying into the other complexities of MI, and it works out
> pretty well IMHO -- but I still miss being able to multiply inherit
> BEHAVIOR as well as just a contract to PROVIDE behavior.

This from someone at Sun? The sky must be falling :-)

Seriously though, as you've mentioned, Java-style interfaces are a
reasonable
tradeoff between the ability of providing mixins and the complexities of
MI. They are good for many things, but not for everything.

As a future evolution, I really do suggest that MI is a feature that
is worthy of consideration in a future evolution of Java. It is not,
however, something that should be tackled without a lot of thought.
I would rather see Java continue without true MI than see a poorly
planned addition --- the potential problems of complexity in a
half-baked
solution are just too great.

For me, at least, MI is a valuable tool for modelling complex systems.
It's lack in Java is a key reason that I do not use Java in serious
work. Introduction of MI will never make me give up other languages,
(I'm too aware that all languages trade off some things against others)
but will make Java a serious option for my work.

Graham Perkins

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
Peter wrote:
> > > As far as I know, multiple inheritance does not present significant
> > > performance problems. The speed hit is minimal.
> >
> > Are you thinking here of technology in Dylan? I don't know it well enough
> > to comment.
>
> I was not thinking of any particular language. I am not an expert in
> this area, and have never implemented inheritance in a language. I base
> my assertion on what I have read in journal papers on the costs of dynamic
> dispatch.
>
> If I remember correctly, a virtual function call in C++ takes about 6
> machine instructions. Multiple inheritance adds a few more instructions I
> think, but only when it's being used.

Although it is some time since I read technical details of ISE Eiffel
system, I seem to remember them claiming that dynamic binding was
constant
overhead, and not affected by the presence of multiple inheritance.

It is certainly easy to see how to implement the jump-tables with
only one extra de-reference instruction per method call to allow for
MI.
So I guess ISE programmers put a little more brainwork in.

------------------

Anyhow I don't see why efficiency should come into it. If the
compiler-writers cannot make MI more efficient than its various
workarounds then they really shouldn't be in the business.

--
http://www.mk.dmu.ac/~gperkins

Graham Perkins

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
Dave Harris wrote:
> If you need it, you need it. MI is one of those many language features
> which are sometimes so essential that if the language doesn't support it
> directly you have to simulate it by hand. Garbage collection and mutating
> classes on the fly are other examples. Simulating it by hand is generally
> less good than having it built in.
>
> It doesn't follow that every language should have everything built in.
> There are costs and trade-offs involved. This is especially sensitive for
> things which incur costs even for code which doesn't use them. So there is
> a judgement call. With its interfaces, Java has found an interesting
> trade-off point. It works for a great many programs.

It works for those programs which needed multiple conformance but
not multiple inheritance. But for *all* those places where you
need true multiple inheritance it fails. The workarounds all
introduce maintenance and performance overheads.

> > I don't think MI is a particular big performance problem driving Eiffel

> > implementations...

> It's surprising what is possible even in a dynamic environment. However,
> it's a difficult and subtle area. To me it seems that not having true MI
> makes dynamic compilation significantly easier. At least you know your
> instance variables aren't going to move about.

I don't see the problem. Dynamically loaded class should bring its
own vtable .. who cares where it *actually* stores anything?

[unless you're fool enough to use public attributes, and your
compiler writers were fool enough to implement public attributes
with really dumb static binding]

If you recompile a class on dynamic load, then provider can
make the instance variable move slots by fiddling the source,
regardless of SI or MI provision. That in fact is a completely
different problem .. how to cope with old instances of a class
which has evolved?

--

http://www.mk.dmu.ac/~gperkins

Graham Perkins

unread,
Apr 13, 1999, 3:00:00 AM4/13/99
to
Ed Falis wrote:
> It's not clear to me what these figures are supposed to demonstrate
> relative to the question. Eiffel applications lean towards
> extensive use of MI as a natural way to do mixins and roles,
> so I personally don't find ...

Maybe mixins, and this is essential if you want to meld
the scopes. But not roles. Programmers who use MI to
implement roles are simply making an amateur mistake.

A very very common use of MI in Eiffel libraries is to
define multiple conformance *and* use Template Pattern at
same time. With Java-like interface approach you can only
manage the former.

--

http://www.mk.dmu.ac/~gperkins

Dave Harris

unread,
Apr 13, 1999, 3:00:00 AM4/13/99