3

我编写了一个定义了许多受保护方法的基类。这些方法在其子类中调用。这些方法为其子类定义了基本操作。例如:

class Base{
   protected void foo(){}
   protected void bar(){}
}

class Sub1 extends Base{//The sub class only needs Base.foo()
   public void po(){
     ...
     foo();
     ...
   }
}

class Sub2 extends Base{//The sub class only needs Base.bar()
   public void ko(){
     ...
     bar();
     ...
   }
}

class Sub3 extends Base{//The sub class needs both Base.bar() and Base.foo()
   public void lo(){
     ...
     bar();
     ...
     foo();
   }
}

我只是想知道这是否是一个好的 OOP 设计?阅读源码,我们知道Sub1根本不需要Base.bar()Sub2根本不需要Base.foo()。我认为这有点多余。但是我不知道更好的解决方案,任何人都可以提供一些建议吗?谢谢!

4

4 回答 4

3

通常,您应该在设计中避免此类对象依赖关系。如果 foo() 和 bar() 的功能在派生类中没有改变,你可能想把它放在一个外部类中并使用那个:

class Base{

}

class Helper1  {
   public void foo(){}
}

class Helper2  {
   public void bar(){}
}

class Sub1 extends Base{
   private Helper1 a = new Helper1();
   private Helper2 b = new Helper2();

   public void po(){
     ...
     a.foo();
     ...
     b.bar();
   }
}

class Sub2 extends Base{
   private Helper2 b = new Helper2();

   public void ko(){
     ...
     b.bar();
     ...
   }
}

这个 foo & bar 的例子看起来不太好。您的问题可能是对对象的责任分配不当或滥用继承。发布真实代码将有助于编写更好的答案。

于 2010-08-22T13:46:03.637 回答
2

抱歉,但你的想法是错误的。问题不是“应该 sub2 继承基础,它不需要那个方法”

问题应该是“sub2 是基础”,例如青蛙是动物吗?是的,青蛙可以继承动物,但青蛙不应该继承哺乳动物。

如果 sub2是一个基础,那么你就在正确的轨道上,如果 base 只是可能有用的函数的集合,那么就有问题了。

于 2010-08-22T13:52:11.797 回答
1

我看到这是 SOLID 规则之一的接口隔离原则问题。

如果您的子类不需要所有基类功能,您可以将基类拆分为更具体的基类或接口

于 2010-08-23T09:55:52.440 回答
1

我的想法

1-如果您是第一次设计,请尝试遵循依赖注入原理,因为我可以清楚地看到您正在不同的子类中创建对象 Helper1 , Helper2 并且也可能是重复代码。

2-如果您不需要 helper1 和 helper 2 的不同实例,或者可能将它们设置为 Virtual 以便您可以在需要时覆盖它们,我建议将 Helper1 和 Helper 2 创建为基类中的属性。

3-您正在直接编写实现,而您的客户端代码直接取决于使用接口的具体类,这将使您的类更具可测试性。

4-这是黄金法则:如果您正在处理的问题不是那么复杂,并且您没有看到在不久的将来改变它们的理由,而是继续使用您正在做的事情,不要让您的生活复杂化。

所有好的 oop 编程都是好的,但是如果你看到一个比实现更简单的解决方案更好更简单的解决方案,因为使用抽象你付出了复杂性的代价。

更重要的一条规则: 看看你是否在不改变设计的情况下轻松测试你的类设计,而不是你的设计是否走上正轨。

于 2010-08-22T14:40:47.593 回答