多态性最佳实践

问题描述 投票:1回答:3

我一直在调查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,但我仍然需要在第一个子类中使用它,否则抛出异常。因为永远不应该在第一个类中调用此方法,所以我只是使用消息抛出异常。这看起来似乎没有通过。这绝对是对继承的错误使用。

如果我只在Second类中使用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();
}

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

java inheritance interface polymorphism abstract-class
3个回答
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 { ... }

3
投票

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

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

通过这种方式,类Table的对象将实现Furniture,但类Chair的对象可能会改为实现RecliningFurniture。两者都受Furniture界面的合同约束,但Chair也必须履行合同RecliningFurniture的附加条款。


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一样,这是肯定的。在其他的,你将不得不提到,我们在这里有更多的东西

© www.soinside.com 2019 - 2024. All rights reserved.