tags:

views:

550

answers:

12

Imagine I have an interface called IVehicle.

From this interface, I derive several concrete types such as bus and car (all can move, slow down, switch off engine, etc). My interface has no fields.

Would it be bad design to have one class which has fields (e.g. top speed of vehicle) and use this by each of the concrete types? Would this be bad design? Also, if I store state in this class (e.g. use the fields), then would it have to be static?

Thanks

+7  A: 

You're talking about an abstract class, and no, it's not bad design. That's what they're for (basically, interfaces, but with some basic implementation).

State wouldn't have to be stored statically. There will be a full implementation of this class (in the form of one of the derived classes) each time you create a Car, Bus, etc.

DannySmurf
composition over inheritance
DevelopingChris
Love over gold. Eggs over easy. It ain't over 'till it's over, baby.
Ori Pessach
@ChanChan - that's a rule. And hard rules are generally bad.
Jason Baker
@ChanChan: Is there some benefit you derive from blindly reciting a development rule you've heard? If not, why not explain why you think composition is better?
DannySmurf
+2  A: 

Just to clear up some confusion...

An interface cannot have fields.

However, it can have properties. Properties that would invariably have to be implemented through code by the objects that implement the interface.

Unless you plan on casting a reference to an object through an interface back to a concrete type, you should put some properties that makes sense into the interface, otherwise you won't be able to reach them.

In other words, if you have this:

IVehicle vehicle = GetVehicle();
// want to get speed of vehicle?
Car car = (Car)vehicle;
Double speed = car.Speed;

Common properties should be put into the common interface. Since a vehicle is a moving object, speed would make sense to have there.

However, the number of engines would make sense for planes and some boats, but not for cars, and such that type of information would probably have to be located into some more specific interfaces.

Static would mean shared between instances, I doubt that would be a good idea.

However, the overall plan to use interfaces instead of just a class hierarchy to separate out the access to and use of an object from its actual type and identity is a good idea, and leads to good design.

The best plan is to pick the level of abstraction that makes sense for your model and go with that. You can over-design such a solution very easily. For instance, you could realize that some vehicles doesn't have engines at all, and some can move in more than one dimension (ie. not just forward/backward, but up/down, sideways, etc.), and picking the level that fits your model is a good start.

For instance, if you're going to model the transportation issues a county has to deal with, whether a plane can move just forward/backward or got vertical rotatable engines or not is moot, so you probably shouldn't try to design that into the solution.

Lasse V. Karlsen
A: 

You're being language-specific. In C++, for example, there are no interfaces, but you can use abstract classes like an interface.

Man, how I love drive-by downvoting. This is a valid answer, as the question is not about OOP, it's about OOP in a specific language that a) has interfaces, and b) makes a distinction between base class-like constructs with or without members. You don't need that distinction to do OOP.
couldn't agree more. I'm not sure about your answer as I don't know c++. However, I feel that if someone downvotes, they should be required to answer why.
asp316
Downvoted because interfaces are language-agnostic enough that it's irrelevant. Yes, language semantics will vary, but if you say "interface" to a Java, C++, or C# programmer, they'll probably all have about the same idea what you mean.
Jason Baker
It's not irrelevant at all. It points out that the question whether or not interface-like classes may have fields is not a question that OOP answers. C++ shows that by example, as whether or not a class can be considered an interface is a question of convention, not one of OO paradigms.
+7  A: 

I would add TopSpeed to the interface as a property like this:

interface IVehicle
{
    void Move();
    void SlowDown();
    void SwitchOffEngine();

    Int32 TopSpeed { get; }
}

Then you implement the interface in your concrete entities like this:

class Car : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
     get { return 120; }
    }
}

class Bus : IVehicle
{
    public void Move() { }
    public void SlowDown() { }
    public void SwitchOffEngine() { }

    public int TopSpeed
    {
     get { return 98; }
    }
}

I think this would be the best approach and doesn't require a base class.

The reason I believe this is the best approach because TopSpeed is a property that is specific to the implementation and will not have any meaning in a base class. Since the base class would require that any implementation set this value anyways I think it is best to change the interface to include it.

Andrew Hare
I'd vote your post up, but you should probably elaborate more on why this is a better approach than using a base class.
Jason Baker
Base classes should only ever be used if you include some sort of base implementation like Abstract Class BaseVehicle : IVehicle.... public virtual void SwitchEngineOff() { TopSpeed = 0; ... } then a client consuming the abstract base could then override what it does. If the abstract class has
Chris Marisic
no implementation then it should be a pure interface.
Chris Marisic
Question: Why Int32, as opposed to good old-fashioned int?
Rob
Rob: Makes no difference. int is an alias of Int32 in .NET.
DannySmurf
+2  A: 

I second DannySmurf, abstract classes are very useful. I use the hide-the-abstract-class-behind-an-interface pattern in class libraries very often so that I can have all the implementation classes, even the abstract parent class, as internal classes, that is, I do not expose the implementations to the client at all.

DrJokepu
Is there an example of this?
dotnetdev
+1  A: 

Would it be bad design to have one class which has fields (e.g. top speed of vehicle) and use this by each of the concrete types? Would this be bad design?

No, not bad design. An alternative is to have a abstract / pure virtual property for each field (e.g. top speed) ... if you have a lot of these properties, and if the properties are simple (e.g. just return a number, don't actually do anything complicated) then your idea of a class which contains the specialized property values seems simpler than having that many more abstract / pure virtual properties.

Also, if I store state in this class (e.g. use the fields), then would it have to be static?

It's OK if it's static, if-and-only-if it applies for every instance of the class. For example, it's OK to define "top speed" as static (all busses have the same top speed), but not "current speed" (different busses actually travelling at different speeds at any given moment).


Just to be clear, I think you're suggesting a design that's something like this:

interface IVehicle
{
  void accelerate();
}

sealed class VehicleProperties
{
  const int topSpeed;
}

class VehicleImplementation : IVehicle
{
  //const data
  const VehicleProperties vehicleProperties;
  //non-const instance/state data
  int currentSpeed;
  //ctor
  VehicleImplementation(VehicleProperties vehicleProperties)
  {
    this.vehicleProperties = vehicleProperties;
  }
  //implement IVehicle methods
  void accelerate()
  {
    if (currentSpeed => vehicleProperties.topSpeed)
      return;
    ... else todo: accelerate ...
  }
}

class Car : VehicleImplementation
{
  //static properties associated with the Car type
  static VehicleProperties carProperties = new VehicleProperties(120);
  //ctor
  Car()
    : VehicleImplementation(carProperties)
  {}
  //IVehicle methods already implemented by
  //the VehicleImplementation base class
}
ChrisW
+6  A: 

You are not breaking OO, in your case-

IVehicle defines "if you are a vehicle what should you be able to do"

AbstractVehicle defines "if you are a vehicle this is the minimum you should be able to do and this is how you would do"

ConcreteVehicle defines " I am a vehicle, this is my way of doing things that I am supposed to be doing since I am a vehicle"

You dont need to put all your properties as static. Something like Max speed or Top speed can be kept static but you could keep them as const too, your call.

Perpetualcoder
+ ConcreteVehicle should encapsulate some VehicleImplementation using composition, not inheritacle effectively being a bridge or adapter. The reason - should you decide to change IVehicle interface, you will only need to change adapters, not whole class hierarchy.
alex
Oh, and by the way, interface segregation principle requires IVehicle to implement separate interfaces, like: ICanMove, IHaveEngine, IHaveSpeed, etc. one method per interface. That's will be a good OOP design.
alex
@alex = I agree with you bro! I was merely scratching the surface since the question was not too much about detailed design. I simply tried to answer by saying that he isnt really breaking OO. You are correct though.
Perpetualcoder
+2  A: 

I think you should use superclasses and not interfaces. So most likely the IVehicle interface is redundant, and you should just have abstract superclass called Vehicle. As it is true that every vehicle can move and thus can have its speed measured, you can add speed as a field to the superclass.

This speed field is in no way static, because it will be instantiated for every concrete instance of Vehicle; if you have two buses, they may have different speeds, so the field cannot be static but must be specific to the instances.

antti.huima
A: 

Another approach, and how I distinguish between abstract classes and interfaces for common scenarios, is:

-All custom behaviour in an interface -Common fields to use in a base class, which can be used and set as required.

I use the hide-the-abstract-class-behind-an-interface pattern in class libraries very often so that I can have all the implementation classes, even the abstract parent class, as internal classes, that is, I do not expose the implementations to the client at all.

Is there an example of this?

dotnetdev
This seems more like a comment than an answer. You might think about putting it as edit in your original question.
Joe Soul-bringer
I did think about that. The problem I have with doing that is I feel a reply would render more visibility than a comment to a certain user. E.g. if I want person A to read something, I feel he might miss my comment but read my reply.
dotnetdev
+1  A: 

If you "add a field to an interface", it stops being an interface and becomes a base class. That might be bad or it might not be, depending on your preferences.

The pattern of using an interface and avoiding base classes with member variable is quite fine. It is especially useful in situations where you pass an interface to another part of a system.

But without a specific context, there is no absolute rule saying "thou must use an interface as one's base class". Using a private member variable in your base class may be a fine first approximation to the functionality you are looking for. Another solution, using a private function defined in the derived class, is more verbose and by that fact alone may make your code harder to understand (though, if everyone in your organization is doing this, that would not be an issue).

It depends on what you would like to accomplish. It also depends on what standard is used in your organization, in your application or even on what language you are using (if you use a language with getters and setters, you can more easily replace member variables at a later time, for example).

Whether a member variable is static or not is a separate issue. You should make a member static if and only it doesn't change over the life of the class. "Top Speed" sounds like it fit this criteria. Some languages, like c++, have the concept of "static functions", whose results don't change. I suppose you could use this as well but I find this added concept too confusing to be worthwhile.

Joe Soul-bringer
+1  A: 

Would it be bad design to have one class which has fields (e.g. top speed of vehicle) and use this by each of the concrete types? Would this be bad design?

No.

IMHO the difficulties with inheritance in C++ (I don't know the case of Java and other languages so well) have helped establish the tradition that "non-leaf classes should be abstract" (it's actually an item of "More Effective C++" by Scott Meyers, if I recall well). But, if anything, putting fields and concrete functionality in a base class is not bad OO design.

In some languages, it may pay off to follow this strategy. In classical OO, and its flag language (Eiffel), this (having concrete, useful base classes if your design leads you to that choice) is exactly the way to go. There are language mechanisms designed to solve any potential problems you could have due to polimorphic use of your code or multiple inheritance.

So, it is not bad OO design; that's for sure. But you should take into account that, in some languages, your natural idea may be traditionally avoided in favour of less natural, but more practical alternatives.

By "your design leads you to that choice" I mean that in your program it makes sense to create instances of "a vehicle". If this is true (for example because you are designing a video game where it is possible to use 'vehicles'), then your design will be right. If in the problem your software is trying to solve it makes no sense whatsoever to create a vehicle (for example because you're managing a parking space and nothing is allowed to be "just a vehicle" - instead you need to have motorcycles, cars, vans, whatever), then of course your design should make vehicle abstract. But there is no universal answer to that.

Also, if I store state in this class (e.g. use the fields), then would it have to be static?

No.

Daniel Daranas
A: 

Yes it is a bad idea. Your definition of IVehicle is so general but you've still made some assumptions. The first is that the max-speed attribute may not have the same units of measure. A child of type Car may have a max speed measured in statute miles while one of Boat or Aircraft would use nautical miles. More about this sort of problem is discussed at this Codewrights Tale post on object identity. There are subtle problems with inheritance that our culture has accepted but never fully examined. If you want to understand those sublties, study how the FAA has to approach the definitions of what 'Aircraft' means so that the regulations can be defined with some semblance of sanity.

Kelly French