我在完成的采访中有一个问题,我不会得到正确的答案。
假设我们有3个类,Base,Derivate1和Derivate 2, 他们的关系如下所示
public class Base {...}
public class Derivate1 extends Base {...}
public class Derivate2 extends Derivate1 {...}
然后我们发现Derivate1和Derivate2对我们的程序来说是不必要的,但它们的方法实现很有用。那么,我们如何摆脱Derivate1和Derivate2但仍然保留他们的方法呢?在这种情况下,我们期望用户无法创建Derivate1和Derivate2的新实例,但他们仍然可以使用Derivate1和Derivate2中的方法实现。当然,我们允许更改Base类中的代码。
你怎么看待它,你能告诉他们实际上在问什么吗?
非常感谢。
PS。
当我对他们进行讨论时,我的面试官会有一些提示。
派生类来自第三方。它们的设计很糟糕,所以我们不希望我们的客户端使用它们,这意味着用户不应该允许从派生类创建实例。
derviate类包含对Base类有用的重写方法,我们可以在Base中创建具有不同名称的方法,以在派生类中实现那些有用的行为。
感谢所有有趣的答案......
答案 0 :(得分:2)
简单的重构:
Derivate1
和Derivate2
复制到Base
。Derivate1
和Derivate2
类Derivate
个对象的指针作为Base
,那么您应该是好的)即使您在层次结构中有更多子类,例如Derivate3
和Derivate4
,也不应该让它们扩展Base
。
答案 1 :(得分:2)
(非静态)来自Derivate1
和Derivate2
的方法仅在我们创建Derivate1
和Derivate2
个实例时才可用。创建Base
实例(与new Base()
一样)将不允许访问在子类中声明的(非静态)方法。
因此,为了保留这些方法,可以将它们添加(重构)到Base
类。如果我们只是不想要子类的公共构造函数但是保持对象图不变,则可以使用工厂模式来按需创建它们。但即使在这种情况下,也必须将工厂返回的对象强制转换为Derivate1
或Derivate2
以使用(非静态)方法。
我想我知道他们想听到什么,共同的建议是“赞成作文而不是继承”。因此,不要说 Derivate1是一个基础,而是执行 Derivate1有一个基础:
public class Derivate1 {
private Base base;
// ... more
}
public class Derivate2 {
private Derivate1 derivate1;
// ... more
}
不再继承,Derivates仍然可以使用以前的超类的方法。
答案 2 :(得分:2)
答案 3 :(得分:1)
我们可以做两件事:
Derivate1
和Derivate2
的某些方法提升为Base
,这是有道理的(如上所述)Derivate1
和Derivate2
abstract
:这会阻止实例化,但不会继承答案 4 :(得分:0)
我认为他们的意思是将衍生物提取到接口
答案 5 :(得分:0)
如果有意义,您可以直接在基类中包含这些方法。但这当然取决于这门课程的意义。如果可能,您可以在实用程序类中使用静态方法。顺便说一下,在这两种情况下,您的开发人员都必须改变对API的使用。
答案 6 :(得分:0)
第一个显而易见的事情是层次结构中的每个类都是具体的 - 通常,类型应该是抽象的,或者是叶子类型。其次,关于这些方法是什么的信息还不够 - 如果它们覆盖了Base或Derived1中的某些东西,你就无法将它们移动到Base中;如果它们是适用于任何Base的实用程序方法,那么它们可能会被移动到Base中,如果它们独立于Base,那么它们可以被移动到辅助类或策略中。
但我会质疑一个类不是必需的,但它的行为是 - 这有点暗示提问者正在设计一个本体而不是一个面向对象的程序 - 一个类存在的唯一原因是提供行为并且一致地封装有用的行为是类存在的充分必要条件。
答案 7 :(得分:0)
由于您不拥有派生类,因此无法删除它们。基类是你的全部,所以你有控制权。客户是你的,所以你有控制权。因此,最好的方法是拥有一个暴露给客户端的全新类。这个类实际上创建了派生实例(注意:你的客户端不再处理它)并使用它们的有用功能。