多态最佳实践

时间:2018-08-29 20:58:58

标签: java inheritance interface polymorphism abstract-class

我一直在研究java设计模式,以使我的项目更有条理,我需要知道的一件事情是,如果以下方法是一种好的做法。

使用父抽象类或接口时,子类的方法在父类中定义。

我的问题是,当我有一堆子类时,如果每个子类都覆盖父级中的方法A,但是其中一个子类需要具有不同的方法B,那么在父级中定义方法B是一种好的做法吗? ,即使仅用于该单个子类。

这带来了一个问题,即使从未从该子类中调用过methodB,也需要在每个子类中使用它。

我打算这样做吗?似乎不正确。

代码示例:

public interface Parent{

  public void methodA();

  //Should this method be in the parent as it is only used once?
  public void methodB();

}

子类:

public class First implements Parent{

  @Override
  public void methodA(){
    System.out.println("This is method A");
  }

  // Does Nothing but java must have it used in the sub class
  @Override
  public void methodB(){
    throw new UnsupportedOperationException("Do not call methodB from class First!!");
  }
}



public class Second implements Parent{

@Override
  public void methodA(){
    System.out.println("This is method A");
  }

  // methodB is being used for this sub-class
  @Override
  public void methodB(){
    System.out.println("This is method B");  
  }

}

从上面的代码中可以看到,我只对第二个子类使用methodB,但是仍然需要在第一个子类中使用它,否则会引发异常。由于永远不要在第一个类中调用此方法,因此我只是抛出一条带有消息的异常。这似乎是无组织的。肯定是对继承的错误使用。

如果我仅在第二类中使用methodB,而不将其添加到父类中:

 public static void main(String[] args) {
   Parent p = new Second();
   p.methodA() // Prints "This is method A"
   p.methodB() // throws an error
 }

有人知道我如何在不抛出错误的情况下调用类中的特定方法。将方法添加到父级绝对是不好的做法。

编辑:

感谢所有快速响应,我发现这样做的方法是定义不同的接口:

interface X {
  public void A()
}

interface Y extends X {
  public void B()
}

class First implements X {
  @Override
  public void A();
}

class Second implements Y {
    @Override
    public void A();

    @Override
    public void B();
}

如果这仍然不正确,请告诉我。

3 个答案:

答案 0 :(得分:3)

interface是实现它的类同意履行的合同。

请考虑一个名为Furniture的假设接口。并非所有的Furniture都会合理地实现recline()方法(例如表格),但有些可能会实现。这是一个很好的示例,为什么recline()方法不应该在此接口中,而应该在扩展接口RecliningFurniture中。

通过这种方式,类Table的对象将实现Furniture,但是类Chair的对象可能会实现RecliningFurniture。两者都将受Furniture接口合同的约束,但是Chair也必须满足合同RecliningFurniture的附加条款。

答案 1 :(得分:2)

  

[...]是在父级中定义方法B的好习惯,即使该方法仅用于单个子类。

当然不会。

想象一下,如果每个子类都添加自己的子类,那么您的超类将以多快的速度增长。每个孩子都有一堆其他子类需要的无关的东西。它表示类之间的关系不正确以及继承的使用不正确。

在您的代码段中,类之间的关系不明确。继承总是需要真实的例子。在这里,我无法声明First is a Parent

对于几乎所有子类都将要实现的方法,我已经看到了使用默认的基于异常的实现在父级中定义该方法的实践。因此,您无需在子类中重复标准行为。

对您当前的状况会有一点改善:

default void methodB() {
     throw new UnsupportedOperationException("[...]");
}

Parent实例传递给方法,请确保仅使用此类提供的接口。这样一来,您就不必投放和破坏其界面。

A -> [methodA] (only)
B -> [methodB] (only)
C -> [methodA, methodB]

如果给定的方法还不够,请创建一个复合接口,该接口将添加缺少的方法:

interface A { void methodA(); }
interface B { void methodB(); }
interface C extends A, B {}

class First implements A { ... }
class Second implements C { ... }

答案 2 :(得分:1)

如果某些对象的行为类似于X,而其他对象的行为类似于 X +其他东西,则您需要2个接口,因为您有2个事物,其中一个与另一个相似,另加一些

interface X {
      public void A()
}

interface Y extends X {
      public void B()
}

class First implements X {
      @Override
      public void A();
}

class Second implements Y {
      @Override
      public void A();
      @Override
      public void B();
}
可以肯定的是,

在需要X的情况下,它们的行为都将像X。在其他情况下,您将不得不提的是,这里还有更多内容