减少没有子类继承的代码重复

时间:2018-01-29 19:16:10

标签: java inheritance interface modularity open-closed-principle

我正在玩子类与接口和组合。在代码重复方面,我最终对一些事情感到困惑。众所周知,有很多场景,其中子类化和继承不是方法,但它在减少代码重复方面是有效的。

接口非常强大,如果操作得当,可以提供很好的可读性,但是我无法理解它实际上并没有帮助我减少代码重复。我们最终可能会遇到子类化无效的情况。但扩展程序的可能性很大,每当我们这样做时,尝试维护Open闭合主体,我们最终会以荒谬的副本进行接口的实现/实现粘贴代码,它可能通过子类化(在代码重复方面)可以避免。

我们如何使用Interfaces和Composition构建出色的策略,避免一遍又一遍地编写相同的方法?通过这种方式,我们可以保持模块化并同时坚持开放式封闭原则。我们是否有任何指导方针可以快速有效地确定代码重复到底是否值得?

干杯

< / wallOfText>

2 个答案:

答案 0 :(得分:2)

面向对象的建模是非常主观的,但我唯一可以解决的问题是旧的继承与组合讨论: https://www.thoughtworks.com/pt/insights/blog/composition-vs-inheritance-how-choose

基于你的论证,我相信你经常尝试从两个或多个具有相似代码的类中提取超类,因此它们都可以共享相同的继承方法而不是仅仅复制它们。虽然从技术上讲这可以为您提供所需的内容,但您还应该注意继承语义,因为它将表示 is-a 关系(即,car 是-a 的车辆,狗是一个哺乳动物,报告屏幕是一个只读屏幕)。由于Java不提供多重继承,如果类层次结构增长,最终可能会受到限制和混淆。

因此,在开始提取超类以供重用之前,请记住,您还可以将此代码 - 我想重用单元提取为部分其他课程(作文)。

很抱歉我的概念性示例,但在这里 Dog Lion 都是哺乳动物和猎人。他们应该自然地继承哺乳动物超类(在哺乳动物中有很多可重复使用的代码)。由于并非所有哺乳动物都在捕猎,我们不希望在哺乳动物类上定义新的 hunt()方法。

在这一点上,您可能正在考虑创建一个新的继承级别: Mammals< - HuntingMammals 。但是想想:如果你继续为动物的每个独特方面做这件事,那么你将会遇到一些棘手和困惑的等级。除此之外,我们也知道一些爬行动物和鸟类也会捕猎,因此,我们最好将所有狩猎物品隔离在其他地方。

作为继承的健康替代方案,我们可以定义一个单独的 Hunter 类。要重用它的内容,我们需要做的就是将 Hunter 对象作为 Dog Lion (一个字段)的成员。如果我们需要将狗和狮子一起视为猎人(多态),我们可以定义一个 CanHunt 接口来对它们进行分组。

检查以下示例:

class Hunter {
   void hunt(){
       System.out.println("i'm hunting...");
   }
}

interface CanHunt{
   Hunter getHunter();
}

class Dog extends Mammals implements CanHunt{
   ...
   Hunter hunter = new Hunter();

   @Override
   Hunter getHunter(){
       return hunter;
   }      
   ...
}


class Lion extends Mammals implements CanHunt{
   ...
   Hunter hunter = new Hunter();

   @Override
   Hunter getHunter(){
       return hunter;
   }      
   ...
}

在这里,我们有一个多态的示例代码,要求狗和狮子都做狩猎:

...
List<CanHunt> hunters = new LinkedList();
hunters.add(new Dog());
hunters.add(new Lion());

for(CanHunt h:hunters){
  h.getHunter().hunt(); //we don't know if it's a dog or a lion here...
}
...

我希望这个简单的例子能给你一些灵感。如果我们不断向更加详细的Flexbile设计发展,它会变得非常复杂。例如, Hunter 类可能是抽象的,具有不同的实现,因为狗从狮子中捕获不同的东西,但它们有一些共同的行为。

答案 1 :(得分:0)

我发现这个问题非常有趣,因为我们大多数人都没有足够的时间来阅读和重新阅读我们可以继承的所有类,这可能导致我们编写非常低效的代码,有时会“重新发明轮子”最后,如果我们看看其他课程,我们将花费更多的时间。

我解决这个问题的建议是创建微服务,小型迷你应用程序,执行特殊的工作,这样你就不必像现在一样使用继承,你就会知道确切的输出你是获得。此外,您可以在其他应用程序中重复使用这些“微服务”。

作为旁注,请查看@AntoineDubuis建议的书籍,我发现它们会非常有帮助。