当需要使用多态指定仅一个子类时,如何设计?

时间:2019-06-13 15:59:24

标签: java oop polymorphism

给出基类 Base ,即 A B C 扩展 Base < / em>。 如果只有 C 中存在特定方法 m()。要调用 m(),您应该首先确定给定的类是否为 C 的类型,一种方法是使用:

Dim myArray(0 To 4) As String

但是我想使用:

otherMethod(Base b){
  if(b instanceof C) 
    b.m();
}

这意味着我必须将 m()方法拉到超类 Base 上,并且只能在类 C 中实现。但是 m() A B 类没有关系,因此不属于它们。这对于代码可读性而言并不直观。那么,对于这种情况,是否有一种更好的设计来使用多态性而又没有不合理的方法位置?

5 个答案:

答案 0 :(得分:0)

如果类C具有任何特定方法,则该类不应成为Base类的一部分。要调用方法m(),您将必须使用instanceof运算符检查实例的类型,然后将Base类转换为C,然后调用方法{{1} }如下

m()

此外,正如其他人已经引用了otherMethod(Base base){ If(base instanceof C){ C c= (C) base; c.m(); } } Collection的示例一样,如果您的类List需要特定的方法,则应创建一个C,可以说它叫interface,它应该扩展Child接口。其他2个类应实现Base接口。类Base应该实现C接口。

现在,当您设计Child接口时,肯定不会知道其他类可以实现哪些特定方法。因此,您也不应在otherMethod中调用任何特定的方法。

答案 1 :(得分:0)

该问题的答案可能会对您有所帮助:Is there a solution to empty methods in subclass?

基本上,它建议您在超类中创建一个空方法,然后根据需要在子类中实现它。但是,它确实警告说这种做法应该是例外,而不是规则,因此使用“ instanceof”实际上可能是更实际的解决方案。

答案 2 :(得分:0)

另一个选择是使用覆盖方法。在Base对象上调用otherMethod()时,它将调用Base中定义的doThings(),除非它是C的实例,该实例已使doThings()重载。

public class Base {

   public void doThings() {
       // nothing happens
   }

   public void otherMethod() {
       doThings(); // will call method above if instance is Base object, will call method below if C object
   }
}

class C extends Base {

   public void doThings() {
       System.out.println( "Things actually get done" );
   }
}

答案 3 :(得分:0)

如果您使用Java 8,而性能不是问题(如果要以60fps渲染10000个形状,则会出现这种情况),然后过滤集合。

假设一个Collection<Shape> shapes

shapes.stream()
      .filter(s -> s instanceof C)
      .forEach(c -> ((C)c).m());

nb。您永远不要在与行为无关的类或接口中声明行为(即方法)。在ernest_k的示例中,不要仅仅因为get(int)使用Collection来将List放在接口Collection<A> justA; Collection<B> justB; Collection<C> justC; 中。这样可以使类结构保持整洁和易于理解。相反,可以通过困难的方式(使用类型检查和强制转换)或通过将不同的子类分离到不同的集合中(从而不必检查类型)来更改类结构的用法。

如果您有这个:

D

那么您就不会遇到这个问题,但是您会遇到另一个(可能更糟)的问题,即每次添加另一个子类(例如<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"> <div> <div class="row justify-content-center text-center"> <div class="btnWrap col-12 col-md-6 col-lg" style=""> <button type="button" id="TopNames" class="btn btn-secondary btn-top active" onclick="topButtonClick(this)">Najpogostejša imena</button> </div> <div class="btnWrap col-12 col-md-6 col-lg" style=""> <button type="button" id="TopBabyNames" class="btn btn-secondary btn-top" onclick="topButtonClick(this)">Imena novorojenčkov</button> </div> <div class="btnWrap col-12 col-md-4 col-lg" style=""> <button type="button" id="TopDisappearingNames" class="btn btn-secondary btn-top" onclick="topButtonClick(this)">Izginjajoča imena</button> </div> <div class="btnWrap col-12 col-md-4 col-lg" style=""> <button type="button" id="TopModernNames" class="btn btn-secondary btn-top" onclick="topButtonClick(this)">Sodobna imena</button> </div> <div class="btnWrap col-12 col-md-4 col-lg" style=""> <button type="button" id="TopLastnames" class="btn btn-secondary btn-top" onclick="topButtonClick(this)">Najpogostejši priimki</button> </div> </div> </div> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js"></script>)时,您都必须在各处更改代码,并且您可能会忘记在某个地方进行更改。

答案 4 :(得分:0)

除了添加$("#companies_table").html("#{escape_javascript(render 'business/companies/partials/companies_table')}"); $("tr[data-link]").click(function() { window.location = $(this).data("link"); })

外,不要感染设计。
Base.visit(IVisitor v) {v.visit(this);}

然后编写所需的IVisitor(此处带有C的实例) 当然,您可以只使用Consumer而不是自己的访问者界面。我只是想说清楚。