OO, Inheritance and Queue

Q

query_me2001

I have a queue that holds a list of objects with a common base type. As
a simple and contrived example, I have a common type of transportation
methods and derived classes (with there own individual methods which
extend the common base class) of Car, Bicycle and Plane:-

class Car : Transport { OpenWindow(); }
class Bicycle : Transport { RingBell(); }
class Plane : Transport { TakeNap(); }

I want to add each of these classes to the buffer. So I can enqueue
with:

Queue transportQueue;
transportQueue.Enqueue(MyCar);
transportQueue.Enqueue(MyBicycle);
transportQueue.Enqueue(MyPlane);

Now this is where I have got concerns. When I dequeue I do not know
what type has been dequeued.

Transport transportMethod;
transportMethod = (Transport) transportQueue.Dequeue();

When I dequeue, I know that it is a transport class but I do not know
if it is a Car, Bicycle or Plane.

I suppose I could use:
switch (typeof(transportMethod))
{
case Car:
break;
case Bicycle:
break;
case Plane:
break;
}

But this does not seem very Object Oriented and not very maintainable.
Is there a better way of doing this?
 
M

Marc Gravell

The ideal would be if you can encapsulate the "do your thing" into a
suitable method that could be used via polymorphism - i.e. (the method name
is for illustration only):

abstract class Transport { abstract protected void
PerformPrimaryFunction();}
class Car : Transport { override protected void PerformPrimaryFunction() {
OpenWindow(); } }
class Bicycle : Transport { override protected void PerformPrimaryFunction()
{ RingBell(); } }
class Plane : Transport { override protected void PerformPrimaryFunction()
{ TakeNap(); } }

Then your queue handler can call .PerformPrimaryFunction() and it all "just
works"...

Marc
 
A

Andy

A better idea would be to not use inheritence in this case. Instead,
look into design patters, such as composition and strategy to achieve
the desired results.
 
S

sloan

There are 2 ways to solve this.

1, as previously mentioned.. is that you have either an Interface or
abstract class with the method.

public interface IVehicle
void DoSomething()

That would mean that Car, Bicycle and Plane implement this interface (or
abstract class), and write their own implmentations of DoSomething

#2 (which piggy backs off of #1)
If you have the Car Bicycle or Transport objects already, then you can look
at one of these design patterns.
Fascade
Adapter

http://www.dofactory.com/Patterns/Patterns.aspx

I'd probably go Adapter.

The key is that you should never/seldom/only once in a blue moon be writing
case statement checking for object type.
At least you were wise enough to ask, instead of plugging ahead.

...
 
Q

query_me2001

Marc said:
The ideal would be if you can encapsulate the "do your thing" into a
suitable method that could be used via polymorphism - i.e. (the method name
is for illustration only):

abstract class Transport { abstract protected void
PerformPrimaryFunction();}
class Car : Transport { override protected void PerformPrimaryFunction() {
OpenWindow(); } }
class Bicycle : Transport { override protected void PerformPrimaryFunction()
{ RingBell(); } }
class Plane : Transport { override protected void PerformPrimaryFunction()
{ TakeNap(); } }

Then your queue handler can call .PerformPrimaryFunction() and it all "just
works"...

Marc

In my example I was trying to create classes that had a commonality but
the derived classes implmented methods that had nothing in common. So
ther could not be found in the base class (PerformPrimaryFunction as
suggested).

Am I wrong but is it not the case that most derived classes will have
extra methods that only apply to this class and not to the base class?
 
Q

query_me2001

I think one of my concerns is how the classes Car, Bicycle and Plane
are passed through the system. Should I have 3 separate overloaded
methods to deal with each class? Or shoudl I have a single class that
deals with the base Class Transport and somehow deal with determining
the actual class within the method?

I had a look at the Adapter and Facade patterns and I didn't really
pick up how they would help.

Also http://www.dofactory.com/Patterns/PatternAdapter.aspx#_self2
seemed to use w few switch statements.
 
J

Jianwei Sun

I think one of my concerns is how the classes Car, Bicycle and Plane
are passed through the system. Should I have 3 separate overloaded
methods to deal with each class? Or shoudl I have a single class that
deals with the base Class Transport and somehow deal with determining
the actual class within the method?

I will use the first option.

I know you have three different methods in each class, but you can do it
that way, you can declare a virtual/abstract method in the Transport
class called
public virtual DoAnyThing();

And in car, you want to declare OpenWindow() as a private method, and
then you want to override this method.

public override DoAnyThing()
{
//Here, you can call the private defined method OpenWindow():
}
 
J

John Liu

I see two ways out here.

Depending on what you want to do in your switch statement.

If you want to call totally independent methods off each of your child
classes (i.e., if you are not after polymorphic behaviour), then
there's no difference here to having a queue<Transport> versus just a
plain object[] transports.

The benefit of having a Transport in the collection is for
polymorphism.

If you are after polymorphism, then something like this is fun - I'll
reuse earlier examples mentioned.

class Transport { virtual PerformPrimaryFunction(); }
class Car : Transport {
void OpenWindow();
override PerformPrimaryFunction() {
OpenWindow();
base.PerformPrimaryFunction();
};
}
class Bicycle : Transport {
RingBell();
override PerformPrimaryFunction() {
RingBell();
base.PerformPrimaryFunction();
};
}
class Plane : Transport {
TakeNap();
override PerformPrimaryFunction() {
TakeNap();
base.PerformPrimaryFunction();
};
}

Then you can simplify your queue logic.
foreach(Transport t in queue)
t.PerformPrimaryFuncion();

jliu - johnliu.net
 
B

Bruce Wood

I think one of my concerns is how the classes Car, Bicycle and Plane
are passed through the system. Should I have 3 separate overloaded
methods to deal with each class? Or shoudl I have a single class that
deals with the base Class Transport and somehow deal with determining
the actual class within the method?

The whole problem here is what do those methods do? What is it about
the Transport object that they need to know / deal with?

If a method needs to do something that is common to all Transport
objects (that is, declared in the Transport class), then there is no
problem. Just pass it a Transport and the method never has to know
which one it is.

If a method needs to do something that is common to some Transports but
not all Transports, then you have an interface scenario on your hands.
Remember: there is no law that says that just because a bunch of types
have a common base class, they can't also implement interfaces. For
example:

public class Car : Transport, IRequiresFuel { ... }

public class Plane : Transport, IRequiresFuel { ... }

public class Bicycle : Transport, IHumanPowered { ... }

etc. Now you're no longer asking, "Is this a plane or a car?" but
rather "Does this transport require fuel?" You can ask that question
easily like this:

IRequiresFuel fueledTransport = givenTransport as IRequiresFuel;

If a method needs to do something that is specific to exactly one
transport type (very rare), then you just have to cast to that exact
type.

Don't try to solve everything within the Transport base class. You're
allowed to use interfaces in addition to that. :)
 

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