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:
- Copy all code from
Derivate1
andDerivate2
intoBase
. - Delete
Derivate1
andDerivate2
classes - Ensure no missing references (if you are already holding pointers to
Derivate
objects asBase
, you should be good) - Compile
- ?????
- 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
andDerivate2
toBase
, when this makes sense (as noted above) - we could make both
Derivate1
andDerivate2
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.
精彩评论