【问题标题】:Java : Override not needed methods inside classes - Update [duplicate]Java:覆盖类中不需要的方法-更新[重复]
【发布时间】:2015-06-22 02:10:06
【问题描述】:

在我的项目中,我有一个包含几个抽象方法的抽象类。现在多个其他类扩展了该抽象类。并非所有类都想覆盖抽象类的所有方法,因为这对他们没有用。如何在对类没有用的子类中提供这些方法的默认实现? 示例-:

public abstract class Animal
{
    public void Action()
    {
     .....
     this.roar();
    } 

    public abstract void roar();

    public abstract void run();
}

上面是抽象类,它将具有子类将实现的抽象方法。

public class Lion extends Animal
{
   @Override
   public void roar()
   {
      s.o.p("Lion roars");
   }

   @Override
   public void run()
   {
      s.o.p("Lion runs");
   }
}

public class Deer extends Animal
{
   @Override
   public void roar()
   {
      // Question : What should I do here?
   }

   @Override
   public void run()
   {
      s.o.p("Deer runs");
   }
}

编辑-:

感谢您的建议,我理解拥有另一个类的想法,该类可以具有不常见的方法(在这种情况下为“咆哮”)。但是我的项目结构有点不同,它有点像遗留代码,其中有许多子类从动物类扩展。子类调用一个具体方法,该方法又调用抽象方法(在本例中为“roar”,请参阅更新后的 Animal 类和具体方法“Action”)。 现在正如你所建议的,如果我创建另一个抽象类

public abstract RoaringAnimal extends Animal
{
    public abstract void roar();
}

这将解决其中一个问题,因为我现在可以扩展 RoaringAnimal,而不是如果 Animal 但其他调用 Animal.Action 方法的类,他们不会在 Animal 中找到 roar() 的实现,javac 会抱怨。

【问题讨论】:

  • 有实现它们的基类吗?
  • 顺便说一句,并不是所有的动物都奔跑。 move() 可能是更合适的方法名称。
  • 查看复合模式,它们有点棘手,但我认为它们更适合这样的应用程序。

标签: java interface overriding abstract-class multiple-inheritance


【解决方案1】:

如果您有一个适用于子类但不适用于超类的方法,例如这里的 roar 方法,那么您可能希望提供另一个抽象类,它继承了 Animal,但提供了 roar,例如, RoaringAnimal。 roar() 方法将不再在 Animal 中声明,而是在 RoaringAnimal 中声明。

public abstract class RoaringAnimal extends Animal
{
    public abstract void roar();
}

那么你可以让Deer扩展Animal,不实现roar(),但是你可以让Lion扩展RoaringAnimal,实现roar()。

【讨论】:

  • 这种模式对于许多具有类似功能的对象是不切实际的。狮子和鹿都想要的jump() 方法怎么样,但龙不想要fly() 方法。你最终会得到RoaringJunpingAnimal、BarkingJumpingAnimal、BarkingRunningJumpingAnimal 等......我认为复合模式的一些想法对于这个应用程序会更好。当然,这取决于他的对象有多复杂或可能变得多复杂。
  • @Neilos 随着复杂性的增加,是的,这变得很麻烦。对于这个例子,它工作得很好。或许RoaringAnimal应该是Lion实现的接口,所以RunningJumpingRoaringAnimal这样的组合是不必要的。
  • 我同意它适用于这个例子,但它很快就会变得比它的价值更麻烦,因为可能有很多组合,这就是我建议复合模式的原因;但这会带来性能上的权衡,因此在提交之前值得考虑。
  • 我继续创建了另一个抽象类,它将具有不常见的方法。但是还有其他多个子类调用 Animal 类并尝试在 Animal 类中找到该不常见方法的声明。我真的无法更改这些子类,因为它有点旧代码,我希望我的更改尽可能被动。 [我已经更新了问题陈述]。
【解决方案2】:

传统上你会这样做:

   @Override
   public void roar()
   {
      throw throw new UnsupportedOperationException();
   }

这个异常实际上是为此目的而创建的

@rgettman 的答案虽然更合适!尽量不要使用这种方法;) 但知道它存在,你可以在核心 Java 库中找到一些示例

【讨论】:

    【解决方案3】:

    在这种情况下,请使用 Adapter 类。适配器类将是一个扩展您的抽象类的具体类,但它基本上会实现它的方法而不用任何东西,或者它的方法实现可以抛出一个扩展 RuntimeException 的异常。

    在 Awt 中有一个很好的例子,它带有 MouseAdapter 类。 See the javadoc here

    这是一个例子:

    class AnimalAdapter extends Animal {
    
        @Override
        public void roar() {
    
            throw new NotImplementedException();
    
        }
    
        @Override
        public void run() {
    
    
        }
    
    }
    

    例如,Sheep 类将扩展 AnimalAdapter,但只有在尝试调用 roar 时才会得到 RuntimeException。

    class Sheep extends AnimalAdapter {
    
        @Override
        public void run() {
            System.out.println("I am a sheep I run, but I don't roar...");
        }
    
    }
    

    此类异常的示例

    class NotImplementedException extends RuntimeException {
    
    }
    

    【讨论】:

      【解决方案4】:

      一种常见的解决方案是称为适配器类的类。这些将使用标准(或空)实现来实现所有方法,并且您会覆盖要更改的方法。缺点是,你不知道动物能不能做这个或那个。

      另一种可能性是将抽象类拆分为接口。通常组合在一起的每组方法都放在一个接口中。然后该类将实现或不实现接口。这最终可能会为您的动物(咆哮、奔跑、爬行......)提供功能接口,然后动物实现将实现它可以实现的接口。接口之间的依赖可以通过接口继承来建立。

      在 Java8 上,可以为接口提供默认方法,这些方法也可以用于您的类。您可以使用带有默认方法的接口,而不是使用抽象基类。

      【讨论】:

        猜你喜欢
        • 2019-05-19
        • 2012-12-23
        • 1970-01-01
        • 2013-08-19
        • 2015-08-20
        • 1970-01-01
        • 1970-01-01
        • 2018-06-19
        • 1970-01-01
        相关资源
        最近更新 更多