是否良好的做法覆盖具有更高可见性的方法?

时间:2014-01-24 16:54:44

标签: java override class-design

回答这个问题:How to GUI - Using paintcomponent() to initialize a GUI and then to add GUI based on mouse我已说过:

  

您没有正确覆盖paintComponent()。这是受保护的   方法,不公开。如果在此方法上添加@Override注释   然后编译器会抱怨。

但@peeskillet明智地指出了这一点:

  

编译器不会抱怨publicprotected   paintComponent。您可以使用更高的可见性覆盖,但不能覆盖   低一个。 public高于protected所以没有问题。

这当然是对的。但现在出现了这样一个问题:良好的实践覆盖是否具有更高的可见度?

附录

链接到JComponent.paintComponent() javadoc。

Netbeans的形象完全没有抱怨:

enter image description here

8 个答案:

答案 0 :(得分:4)

来自Java教程,Controlling Access to Members of a Class

  

如果其他程序员使用您的课程,您需要确保错误   从滥用不可能发生。访问级别可以帮助您实现此目的。

     
      
  • 使用对特定成员有意义的最严格的访问级别。除非你有充分理由不使用私人,否则请使用私人。
  •   
  • 避免除常量之外的公共字段。 (本教程中的许多示例都使用公共字段。这可能有助于说明一些内容   简明扼要,但不建议用于生产代码。)公开   字段往往会将您链接到特定的实现并限制您的   更改代码的灵活性。
  •   

此建议旨在reduce coupling

  

要实现最佳封装(信息隐藏),您应该这样做   始终声明具有最低可见性的方法。在小   程序确实没有问题,但在大型程序中存在这个问题   过度耦合非常严重。耦合发生在一个部分   取决于另一个的具体实施。耦合越多   因为太多而变得更加昂贵   代码取决于具体的实现。这导致软件腐烂 - a   程序变得越来越不可用,因为它不容易   升级。

因此,提高知名度实际上不是一个好主意。这样的代码可能会在未来的开发和维护中遇到麻烦。

答案 1 :(得分:4)

执行此操作的一个原因是,如果您有一个方法需要覆盖项目中的其他位置,并且当前范围不允许您这样做。通常在使用默认值而不是受保护时。

通过在项目的其他位置使用修改范围在正确的包中创建新的子类,然后可以在代码中创建一个您需要它的匿名类,因为您现在可以覆盖麻烦的方法而不必执行反射(这使得代码非常难以理解)。

这也是图书馆课程永远不会成为最终版本的原因,因为那时你不能做这样的事情。


编辑:我被要求详细说明为什么这与依赖注入有关。我只能根据自己的经验说话,首先是Guice,现在是Dagger。

Dagger使用构造函数注入,这基本上意味着一个类将所有依赖项作为构造函数的参数提供(并且仅在那里),并且将它们绑定在一起的粘合代码列在Dagger @Module中。在这个模块中,通常使用日志语句或提供自定义toString()方法返回库类的子类进行扩充非常方便。为了实际 DO 这没有反射技巧,clasess不能是最终的,你需要能够覆盖方法并直接使用超类中的字段。因此,最终的类和两种类型都不需要至少protected而不是private

(我强烈建议使用Dagger,因为它会在java编译器中移动依赖项解析,为IDE提供帮助您在编译时解决问题所需的信息,而不是依赖于野外运行时的魔法。我是仍然对Java生态系统中的洞察力感到惊讶,Dagger设计师甚至不得不获得这个想法,然后意识到它)

答案 2 :(得分:1)

如果您需要从它所在的类/子类外部访问该方法,那么解决方案是使用public参数覆盖可见性。最佳做法是尽可能降低您的变量和方法。

答案 3 :(得分:1)

您可以提高方法的可见性,使其变得更加可见但不太可见,因此可以覆盖paintComponent并将其声明为public方法。话虽如此,我还要补充一点,你不应该这样做。覆盖方法时,您应该保持可见性不变,除非您有充分的理由使其更加可见。

答案 4 :(得分:1)

从OOP的角度来看,它没有任何问题。通过扩展课程,您可以执行以下操作:

  • 更改部分功能(通过覆盖方法)
  • 扩展类的接口(通过添加新的公共方法)

当你覆盖一个方法并改变它的可见性时,你正在做两件事:你 - 显然 - 改变了功能,但也扩展了界面。从类'客户端的角度来看,您实际上是在类'接口中创建一个新方法。这个新方法巧合地与超类中的某个内部方法具有相同的名称,但客户端并不关心(或者甚至不知道这一点)。那你为什么不呢?

另一方面,有一个问题“为什么你需要这样做?”。超类的作者可能对这种方法的可见性有一些想法,发现它的功能并不适用于外部世界。 我并不是说这样做是错误的,但你必须质疑你提高可见度的动机,因为它可能暗示你的或者超类的代码可能是糟糕的设计。

Btw:正如所指出的那样here禁止使用这种语言功能甚至可能是有害的。

答案 5 :(得分:0)

如果您希望外部代码能够调用它们,那么重写的方法就像所有其他方法一样,只应声明public(除非您没有选择,因为重写的方法被声明为public)。在您的情况下,重写的方法paintComponent只应由Swing调用,因此保持protected是最佳选择。

答案 6 :(得分:0)

要添加弗朗索瓦所说的话,这里的OOP原则是“Open Close Principle”,它表示你应该能够扩展,但不能修改对象。通过覆盖它来“提升”方法的可见性只是弗朗索瓦指出的扩展。

答案 7 :(得分:0)

有许多论据可以改变可见性。但只要考虑一下你将改变该类的接口(在API意义上)这一事实。阅读evolving APIs并将该信息与您的问题相关联。

因此,在我的书中,良好的做法是不改变可见性 - 如果可能的话。否则你必须仔细考虑后果 - 如果只是从长远来看。