Multiple Base Classes in .Net

R

Rory Becker

Appologies for starting a separate thread with the same name, but I don't
seem to be able to reply to the other thread without crashing my newsreader(Omea
pro).

Anyway.. to the point....

I would be very grateful if Chris Mullins (or indeed anyone else who has
an opinion) would care to express for me some real world situations in which
multiple base classes are a "better" or "more suitable" or "Simpler" solution
to a given problem.

Thanks very much in advance
 
S

Scott M.

I'm not sure what scenario you had in mind, but first, I'd say that one
class can have only one base class (.NET has multi-level inheritance, not
multiple inheritance).

Do you mean why would "C" inherit from "B" and "B" inherit from "A", rather
than just building one class that has all of "A's" and "B's" characteristics
and just have "C" inherit from that?

If so, my answer would be that it misses the whole point of OO - -
encapsulation and reusability. By working is small units of functionality
and the most basic "types", you form building blocks that can be utilized in
exponentially more ways than if you just build some mega-class.

-Scott
 
R

Rory Becker

I'm not sure what scenario you had in mind, but first, I'd say that
one class can have only one base class (.NET has multi-level
inheritance, not multiple inheritance).

I understand that completely. I have been programming in .Net since the beta
stages of 1.0.

Never the less, I am talking about inheriting from multiple base classes.
This is intended to be a theoretical discussion which follows on from a thread
of exactly the same name as this one.
Do you mean why would "C" inherit from "B" and "B" inherit from "A",
rather than just building one class that has all of "A's" and "B's"
characteristics and just have "C" inherit from that?

No. I mean A directly inheriting from B and C
If so, my answer would be that it misses the whole point of OO - -
encapsulation and reusability. By working is small units of
functionality and the most basic "types", you form building blocks
that can be utilized in exponentially more ways than if you just build
some mega-class.

I am quite happy with single inheritance, encapsulation, polymorphism, reusability,
patterns etc.

I am not looking for someone to tell me why Multiple inheritance is bad.

Quite the opposite in fact. I am looking to broaden my mind by asking Chris
(and others) why multiple inheritance might be a good thing.

It is my position (for what it's worth) that a solution implemented using
SI and Interfaces may be a more reusable implementation than one implemented
using MI.

However, I do not have a lot of experience in this area, so I am asking for
examples for comparison.
 
C

Chris Mullins [MVP]

That's easy - anywhere .Net defines my inheritence tree becomes a good case.

Let's say I have a business Entity called "User Roster".

Let's say I want to build a .Net Windows Forms control called "User Roster".
This control MUST inherit from "control", I've got no choice about it. This
means I'm stuck encapsulating a "Business.UserRoster" inside my control, and
exposing everything I want manually. If I want to be able to pass my roster
back down into the business layer for processing, I can't pass this class -
I need to pass the encapsulated class.

If I had multiple inheritence, I could be both "A control" and "A User
Roster". This means I didn't have to write ANY extra code, and I can pass my
control around, and down into the business layer for processing as a Roster.
Very handy.

The thing hold true for any Enterprise Services work: Anything I want to be
serviced MUST inherit from "ServicedComponent". This means if I want to
stick alot of Business.UserRoster classes into COM, I can't use inheritence.
MI solves this problem nicely.

At a more classic level, the bowels of our SDK have alot of code for stream
and socket manipulation. We have classes such as "XMLStreamReceiver"
"XMLStreamSender", and then classes that manually stitch these two together
into a bidirectional stream. We've got "XMPPSocket" which manually
aggrigates a number of different stream types - an xml stream (for stanzas),
encrypted data, compressed data, binary data, etc. Multiple Inheritence
would have eliminated hundreds (thousands?) of lines of this code.

We've got many classes that interact with our Trace Infrastructure. We
solved this by having a [Tracable] attribute, and some aggrigated code in
each traceable class. It would have been MUCH easier to have trace as a pure
aspect, and each class that was traceable just inherit from the Traceable
class. Lots of code would disappear.

We've got a few hundred custom performance counters, all stemming from our
"SafePerformanceCounter" class. Any class that wants to use these, is stuck
declaring them member variables, and writing a fair bit of code to tickle
the things at the right times. Multiple inheritence could have easily solves
this with an "inherits InstrumentedClass" case, and, again, many, many, many
lines of code would disappear.

In our server, we have handlers setup to handle different types of data that
come in. These handlers (by design) are required to inherit from our
"PacketHandlerBase" class. This means any handler that want to do custom
stuff, has to aggrigate that custom stuff. So, for example, if we want to
Packet Handling class to act like a stream (so it can be exposed to the huge
stream processing infrastructure that we have), there's alot of custom code
that need be written.

All of these can be (indeed, have been) worked around - but it's a clumsy
workaround, where MI would have provided a much more elegant solution.
 
S

Scott M.

Rory Becker said:
I understand that completely. I have been programming in .Net since the
beta stages of 1.0.

Never the less, I am talking about inheriting from multiple base classes.
This is intended to be a theoretical discussion which follows on from a
thread of exactly the same name as this one.

Since you posted a new message, it's reasonable to assume that replies might
not have read the original thread. Since I did not read your first thread,
I was simply trying to understand your scenario.
No. I mean A directly inheriting from B and C

I am quite happy with single inheritance, encapsulation, polymorphism,
reusability, patterns etc.

I am not looking for someone to tell me why Multiple inheritance is bad.

You asked a vauge question and a response like this just makes you sound
arrogant. Why don't you post a message explicitly stating what you are
"not" looking for, so we don't have to be berated by you for passing
information along that we thought could be useful.
Quite the opposite in fact. I am looking to broaden my mind by asking
Chris (and others) why multiple inheritance might be a good thing.

But you don't want to hear why Multiple Inheritance is bad, right? And, you
aren't going to be clear in your post about what it is you are actually
asking? And, you are going to post a new message and expect that all
replies will have read some *other* post you made?

Doesn't sound like you are trying to broaden your mind at all.
It is my position (for what it's worth) that a solution implemented using
SI and Interfaces may be a more reusable implementation than one
implemented using MI.

Gee, I thought that's what I said.
However, I do not have a lot of experience in this area, so I am asking
for examples for comparison.

But you don't want any replies that fall outside of what you want, right?
 
R

Radek Cerny

Well said.

My comments: I am an MI fanatic, but sadly have come to accept we will never
get it in the .NET CLR. The generic case in favour of MI is when
'orthoganal' features are being described and modelled.

MI is like sight. I you have it and lose it, it is devastating. If you
never had it, you dont know what the fuss is about.

It digs deeper than coding - it is a way of modelling and looking for
patterns. I grew up looking for patterns - all patterns - knowing I could
implement using MI. Today I have to look for patterns that are
implementable using SI, which in some cases is quite difficult.

Thanks for the examples.

Cheers,

Radek

Chris Mullins said:
That's easy - anywhere .Net defines my inheritence tree becomes a good
case.

Let's say I have a business Entity called "User Roster".

Let's say I want to build a .Net Windows Forms control called "User
Roster". This control MUST inherit from "control", I've got no choice
about it. This means I'm stuck encapsulating a "Business.UserRoster"
inside my control, and exposing everything I want manually. If I want to
be able to pass my roster back down into the business layer for
processing, I can't pass this class - I need to pass the encapsulated
class.

If I had multiple inheritence, I could be both "A control" and "A User
Roster". This means I didn't have to write ANY extra code, and I can pass
my control around, and down into the business layer for processing as a
Roster. Very handy.

The thing hold true for any Enterprise Services work: Anything I want to
be serviced MUST inherit from "ServicedComponent". This means if I want to
stick alot of Business.UserRoster classes into COM, I can't use
inheritence. MI solves this problem nicely.

At a more classic level, the bowels of our SDK have alot of code for
stream and socket manipulation. We have classes such as
"XMLStreamReceiver" "XMLStreamSender", and then classes that manually
stitch these two together into a bidirectional stream. We've got
"XMPPSocket" which manually aggrigates a number of different stream
types - an xml stream (for stanzas), encrypted data, compressed data,
binary data, etc. Multiple Inheritence would have eliminated hundreds
(thousands?) of lines of this code.

We've got many classes that interact with our Trace Infrastructure. We
solved this by having a [Tracable] attribute, and some aggrigated code in
each traceable class. It would have been MUCH easier to have trace as a
pure aspect, and each class that was traceable just inherit from the
Traceable class. Lots of code would disappear.

We've got a few hundred custom performance counters, all stemming from our
"SafePerformanceCounter" class. Any class that wants to use these, is
stuck declaring them member variables, and writing a fair bit of code to
tickle the things at the right times. Multiple inheritence could have
easily solves this with an "inherits InstrumentedClass" case, and, again,
many, many, many lines of code would disappear.

In our server, we have handlers setup to handle different types of data
that come in. These handlers (by design) are required to inherit from our
"PacketHandlerBase" class. This means any handler that want to do custom
stuff, has to aggrigate that custom stuff. So, for example, if we want to
Packet Handling class to act like a stream (so it can be exposed to the
huge stream processing infrastructure that we have), there's alot of
custom code that need be written.

All of these can be (indeed, have been) worked around - but it's a clumsy
workaround, where MI would have provided a much more elegant solution.
 
R

Rory Becker

Hello Chris Mullins [MVP],
Let's say I want to build a .Net Windows Forms control called "User
Roster". This control MUST inherit from "control", I've got no choice
about it. This means I'm stuck encapsulating a "Business.UserRoster"
inside my control, and exposing everything I want manually. If I want
to be able to pass my roster back down into the business layer for
processing, I can't pass this class - I need to pass the encapsulated
class.

If I had multiple inheritence, I could be both "A control" and "A User
Roster". This means I didn't have to write ANY extra code, and I can
pass my control around, and down into the business layer for
processing as a Roster. Very handy.

Thanks Chris. You have given several examples (and I did ask didn't I :)

I would like to address them individually if I might. Perhaps in seperate
posts as I am limited in the time I can use whilst at work :)

I see that this might be quite involved (well from my perspective anyway :))
So please bear with me here....I'm writing my thoughts on this to clarrify
them in my own mind as much as anything else.

Ok... now let me see... *If* I was to try to solve this with SI etc...

....I would have UserRoster implement IUserRoster
....I would create MyControl which would inhrerit from Control
....I would create a property on Mycontrol of type IUserRoster
....I would assign an UserRoster to this Property

In truth a simpler version would not even bother using IUserRoster and would
make the property of Type UserRoster.

This seems to be an example of where aggregation is more appropriate than
SI at least.
Do you feel that MI is a better solution again. If so could you explain why.

Thanks again
 
C

Chris Mullins [MVP]

Rory Becker said:
Ok... now let me see... *If* I was to try to solve this with SI etc...

...I would have UserRoster implement IUserRoster ...I would create
MyControl which would inhrerit from Control
...I would create a property on Mycontrol of type IUserRoster
...I would assign an UserRoster to this Property

In truth a simpler version would not even bother using IUserRoster and
would make the property of Type UserRoster.

They're not the same solution at all though - in this case, your WinForms
control is NOT a user roster, so anything that would have taken advantage of
that can't happen. You can't pass your control around as if it was a roster,
because it's not. This means alot of additional state management. Ick.
This seems to be an example of where aggregation is more appropriate than
SI at least. Do you feel that MI is a better solution again. If so could
you explain why.

I like the MI solution here much more.

In today's .Net world, I do typically have "UserRosterControl" that defined
"public UserRoster UserRoster{get; set;}", but that doesn't mean I like it.
 
R

Rory Becker

Rory Becker said:
They're not the same solution at all though - in this case, your
WinForms control is NOT a user roster, so anything that would have
taken advantage of that can't happen. You can't pass your control
around as if it was a roster, because it's not.

Why would I pass the control around?

If a method called for an IUserRoster, I would pass a reference to the property.

As far as I can see, the MI method of solving this problem tightly couples
the 2 concepts to each other, making thm impossible to test in isolation.
I like the MI solution here much more.

In today's .Net world, I do typically have "UserRosterControl" that
defined "public UserRoster UserRoster{get; set;}", but that doesn't
mean I like it.

Yes I understand *that* you like it (MI) better... What I'm trying to understand
is *why*.

If it's purely a personal taste thing, I can live with the idea that we just
prefer different aproaches. But I need to know if I'm missing something bigger.
 
P

Paul Wardle

One thing I tried to do was aggregate an interface. (Its not multiple
inheritance, I realize that).

I wanted to do something like the simplified example below. However it won't
compile - I get "Error CS0552: user-defined conversion to/from interface".

This seems like an arbitrary restriction to me and prevents me from
aggregating interfaces to other objects. Of course, aggregating an interface
may lead to ambiguity (i.e. you implement the interface and provide an
operator to do the same) but the compiler can detect that.

I can aggregate the real object but just not the interface (I can change the
operator to return an object of type DoStuff and it compiles and runs OK !!)

I have searched the web and see no reason why I should get this error...?
Does anyone have a clue?

Example:

namespace Aggregate
{
class Program
{
static void Main()
{
DoStuffAndMore dsam = new DoStuffAndMore();
Execute(dsam);
}

private static void Execute(DoStuff ds)
{
ds.DoIt();
}
}

public interface IDoStuff
{
void DoIt();
}

public class DoStuff : IDoStuff
{
public void DoIt()
{
Console.WriteLine("DoIt called");
}
}

public class DoMore
{
// STUFF
}

public class DoStuffAndMore : DoMore
{
public static implicit operator DoStuff(DoStuffAndMore o)
{
return o._doStuff;
}

// public static implicit operator IDoStuff(DoStuffAndMore o)
// {
// return o._doStuff;
// }

private DoStuff _doStuff = new DoStuff();
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top