为什么setter在接口上不好?

Vla*_*mir 3 oop interface

如果我们谈论域对象,为什么setter在接口上是坏的?

澄清:

我有一个存储在db中的域对象.它有几个领域,设置成本很高.即

class JurasicPark {

  private long area;

  ...other fields ...

  getters and setters

  ....

  private Collection<Dinosaur> dinosaurs;
  private Collection<ExoticTree> flora;

  public Collection<Dinosaur> getDinosaurus(){
      ...
  }

  public Collection<ExoticTree> getFlora(){
      ...
  }


}
Run Code Online (Sandbox Code Playgroud)

字段dinosaurs并且flora初始化和设置成本非常高.但在许多情况下,我不需要每次都设置这个字段.

问题是,如果我返回到JurasicPark类的用户实例,dinosaurs或者flora没有初始化它,那么填充导致NPE或我自己投掷的一些预期.我不想让api用户考虑这个并记住哪些字段可能没有设置.

因此,为了解决这个问题,我考虑创建两个接口IJurasicPark,IFullJurasicPark第一个将所有访问方法声明为简单字段,前者将声明访问方法floradinosaurs字段.

   interface IFullJurasicPark extends IJurasicPark

    class IJurasicPark implements IFullJurasicPark
Run Code Online (Sandbox Code Playgroud)

在这种方法中IJurasicPark接口将包含getter和setter,所以我实际上问这个设计是不是很糟糕?

我也不想在使用LazyInit异常的hibernate风格中实现它.

Pét*_*rök 10

谁告诉你的?一般来说肯定不是这样.

在某些情况下,有关财产不应由外部各方修改,这可能是真的.例如,不可变类的接口肯定不能包含setter.

确实,在设计界面时应该仔细考虑,而不是盲目地为类的所有属性自动生成getter + setter.但这并不意味着制定者总是很糟糕.

澄清问题后更新

您的澄清完全改变了这个问题......您可以立即从这个问题开始,从而节省了您和其他人的时间.虽然没有我的投诉 - 我得到了很多(不当的)赞成票:-)

所以你的问题是在域对象中初始化/设置昂贵的集合属性.我的第一种方法确实是延迟加载/保存,可以根据上下文以许多不同的方式实现.

您的帖子建议(但未明确说明)有问题的集合是从数据库中提取/持久存储到数据库中的.但是,您没有提到您使用的持久性解决方案.你也没有解释为什么你不想要一个"Hibernate style lazy init" - 恕我直言,它在大多数情况下非常有效且易于使用.如果您向我们提供有关这些的更多详细信息,我们可能会提供更好的答案.

如果没有恐龙和植物群的JurassicPark对象具有逻辑意义并且可以按原样使用,那么您建议的界面分裂可能是有意义的.同样,如果没有更多的背景,很难判断这一点.您似乎正在根据实现细节做出设计决策,这一般不是一个好主意.

如果你真的想要这样,你实际上不需要单独的接口 - 只需定义一个JurassicPark包含简单成员及其访问器方法的(抽象)基类,然后将其子类化为另一个添加重量级字段的类.