سؤال

OK, this has happened to me many times now so I might as well ask the community. I often have a problem deciding whether declaring something as an instance or as an is-a inheritance (and declaring an instance of sub-class), is suitable.

For example,

  public class BaseStation{
             public BaseStation( int x, int y ){
                    this.x = x;
                    this.y = y;
             }

             public void setX( int x ){ this.x = x; }
             public void setY( int y ){ this.y = y; }

             private int x;
             private int y;
    }

Now if staticBaseStation is-a BaseStation whose (x,y) don't change and dynamicBaseStation is-a BaseStation whose (x,y) do change, can't I just declare static and dynamic BaseStations as separate objects with dynamicBaseStation calling setX, setY everytime it's location changes? But I feel like violating OO principles by doing so.

So basically how do I decide whether to employ inheritance when it feels just like extra-work?

هل كانت مفيدة؟

المحلول

It depends of how you define the contract of the classes.

a) If you specify that BaseStation values can change (or you do not specify that it cannot change), you can use two instances of the class.

b) If you specify that BaseStation values cannot change, then you not only cannot use two instances of the same class for that usage, but you cannot even extend BaseStation to get your DynamicBaseStation (as the subclass would violate the superclass contract). You would need to set maybe a common interface.

The stricter your contracts are, the less reusable the classes will be. But also, as the behavior of the classes is better defined, you can use its properties to simplify using the class/avoid mistakes (the a approach would let you change the values of a StaticBase, the b approach forces you to use another class that is, at best, a sibling).

In this concrete class, I would define BaseStation without specifying that it cannot be moved, and create a StaticBaseStation that refines the parent contract (but does not contradict it) but stablishing that it cannot change its location. Usually the procedure is to increase the restrictions as you go down through the inheritance (specialization).

Anyway, again, it is a rule of thumb. There may be other motives that force you to define the contract one way or the other; the important is that you do not break when extending the classes.

نصائح أخرى

I think an interface would be more appropriate in this situation, since the derived StaticBaseStation would not use any of the super classes methods, however you may want to be able to use either type in certain situations.

For instance, if these classes share an interface you could write methods that accepted the interface as arguments, which would allow you to reuse these methods for both types.

You can employ inheritance when the derived classes are all substitutable for each other... and no knowledge about the derivatives is needed by consumers when they use the base class.

Your example violates the Liskov Substitution principle. If the DynamicBaseStation is used in a context where StaticBaseStation is expected, bad things (unexpected behavior) may occur.

Check out the Liskov Substitution principle here or directly here.

In any case, I'd favor composition over inheritance whenever possible. Inheritance can get you into trouble, as where composition can -mostly- do little harm, but still allow you to change implementation details behind an abstraction. See this question/answer.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top