开发者

How can we get rid of unnecessary inheritance?

I have got a question in my finished interview that I wouldn't get the right answer.

Assume that we have 开发者_开发技巧3 class, Base, Derivate1 and Derivate 2, Their relations are shown as follow

public class Base {...}

public class Derivate1 extends Base {...}

public class Derivate2 extends Derivate1 {...}

Then we found out that Derivate1 and Derivate2 are unnecessary for our program, but their method implementations are useful. So, how can we get rid of Derivate1 and Derivate2 but still keep their methods? In this case, we are expecting that user cannot create new instance of Derivate1 and Derivate2, but they still can use the method implementations in Derivate1 and Derivate2. Of course, we are allow to change the code in class Base.

What do you think about that and can you tell what they're actually asking?

Thanks a lot.

PS.

There are abit of hints from my interviewer when I have discuss the them.

  • The derivate classes are from the third party. They are badly design, so we don't want our client to use them, which means user should not allow to create instance from the derivate classes.

  • The derviate class contains overriding methods that are useful for the Base class, we can create method with different name in the Base to implement those useful behavious in derviated classes.

And thank you for all those interesting answers...


Simple refactoring:

  1. Copy all code from Derivate1 and Derivate2 into Base.
  2. Delete Derivate1 and Derivate2 classes
  3. Ensure no missing references (if you are already holding pointers to Derivate objects as Base, you should be good)
  4. Compile
  5. ?????
  6. Profit!

Even if you have more subclasses such as Derivate3 and Derivate4 down the hierarchy, there should be no problem in having them extend Base.


(non-static) Methods from Derivate1 and Derivate2 are only usable if we create Derivate1 and Derivate2 instances. Creating a Base instance (like with new Base()) will not give access to (non-static) method declared in subclasses.

So to keep the methods, one could add (refactor) them to the Base class. If we just don't want public constructors for the sub classes but keep the object graph as it is, on could use a Factory pattern to have them created on demand. But even in this case one had to cast the object returned by the factory to either Derivate1 or Derivate2 to use the (non-static) methods.


I guess I know what they wanted to hear, the common recommendation 'favour composition over inheritance'. So instead of saying Derivate1 is-a Base you do a Derivate1 has-a Base:

public class Derivate1 {
  private Base base;

  // ... more
}

public class Derivate2 {
  private Derivate1 derivate1;

  // ... more
}

No more inheritance and both Derivates can still use methods of their former super classes.


From the hints they gave you, I think the answer was adapter pattern, which sometimes is used for legacy code.

You can have a look at it here:

http://en.wikipedia.org/wiki/Adapter_pattern


We could do two things:

  • we could pull up some methods of Derivate1 and Derivate2 to Base, when this makes sense (as noted above)
  • we could make both Derivate1 and Derivate2 abstract: this prevents instantiation, but not inheritance


I think they meant extracting derivate to interface


If it makes sense, you can directly include these methods in your base class. But it depends on the meanings of this class, of course. If it is possible, you could ty to use static methods in a utility class. By the way, your developers will have to change their use of the API in both cases.


The first obvious thing is that each of the classes in the hierarchy is concrete - in general, either a type should be abstract, or a leaf type. Secondly, there isn't quite enough information as to what these methods are - if they override something in Base or Derived1, you can't move them into Base; if they are utility methods which would apply to any Base then they might be moved into Base, if they are independent of Base then then they could be moved into a helper class or a strategy.

But I would question the idea that a class is not required but its behaviour is - it sort of implies that the questioner is looking at designing an ontology rather than an object oriented program - the only reason a class exists is to provide behaviour, and coherently encapsulating a useful behaviour is a sufficient and necessary condition for a class to exist.


Since you do not own the derivate classes you cannot delete them. The base class is all yours so you have control. The client is yours so you have control there. So the best way would be to have an all new class that is exposed to the client. This class essentially creates the derivate instances (note: your client isn't dealing with it anymore) and use their useful functions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜