何时编写静态方法与实例方法的编码是否有经验法则?

时间:2009-01-23 23:46:22

标签: java oop class-design

我正在学习Java(和OOP),虽然它可能与我现在的位置无关,但我想知道SO是否可以分享一些常见的陷阱或良好的设计实践。

13 个答案:

答案 0 :(得分:14)

要记住的一件重要事情是静态方法不能被子类覆盖。在代码中引用静态方法实际上将它与该实现联系起来。使用实例方法时,可以根据实例的类型改变行为。你可以利用多态性。静态方法更适合功能性类型的操作,其中行为是一成不变的。比如base 64编码或计算校验和。

答案 1 :(得分:9)

我认为任何答案都没有达到何时选择其中一个的OO的核心。当然,在需要处理实例成员时使用实例方法,但是您可以将所有成员公开,然后编写一个静态方法,该方法将类的实例作为参数。你好C。

您需要考虑您正在设计的对象的消息。那些将永远是你的实例方法。如果您以这种方式考虑您的对象,you'll almost never have static methods。静态成员在某些情况下是可以的。

我们想到的值得注意的例外是Factory Method和Singleton(使用节制)模式。当你想写一个“帮助者”类时要谨慎,因为从那里开始,这是程序编程的一个滑坡。

答案 2 :(得分:2)

如果方法的实现可以完全根据类的公共接口(没有向下转换)来表达,那么它可能是静态“实用”方法的良好候选者。这允许您维护最小的接口,同时仍然提供代码的客户端可能使用很多的便利方法。作为Scott Meyers explains,这种方法通过最小化由类的内部实现的更改影响的代码量来鼓励封装。 {2}由Herb Sutter分开std :: basic_string决定哪些方法应该是成员,哪些方法不应该成为。

在像Java或C ++这样的语言中,我承认静态方法使代码不那么优雅,所以还有一个权衡。在C#中,扩展方法可以为您提供两全其美的优势。

如果由于某种原因需要由子类覆盖操作,那么当然它必须是一个实例方法,在这种情况下你需要考虑设计一个继承类的所有因素

答案 3 :(得分:1)

我的经验法则是:如果方法执行与类的特定实例相关的任何事情,则无论它是否需要使用类实例变量。如果您可以考虑某种情况,您可能需要使用某种方法而不必引用该类的实例,那么该方法肯定应该是静态的(类)。如果此方法在某些情况下也需要使用实例变量,那么最好创建一个单独的实例方法来调用静态方法并传递实例变量。性能方面我相信可以忽略不计(至少在.NET中,尽管我认为它与Java非常相似)。

答案 4 :(得分:1)

如果保持对象的状态(值)并且该方法用于访问或修改状态,则应使用实例方法。

即使方法没有改变状态(实用程序功能),我也建议你使用实例方法。主要是因为这种方式你可以有一个子类来执行不同的操作。

对于其他人,您可以使用静态方法。

:)

答案 5 :(得分:1)

您的默认选择应该是实例方法。

答案 6 :(得分:0)

这个线程看起来很相似:Method can be made static, but should it? C#和Java之间的差异不会影响它的相关性(我认为)。

答案 7 :(得分:0)

如果它使用实例变量,则它必须是实例方法。

如果没有,那取决于你,但如果你发现自己有很多静态方法和/或静态非最终变量,你可能想要将所有静态内容提取到一个新的类实例中。 (一堆静态方法和成员是单例,但是真的很烦人,有一个真正的单例对象会更好 - 一个常规对象,恰好是最好的!)。

答案 8 :(得分:0)

基本上,经验法则是它是否使用特定于对象的任何数据,实例。因此Math.max是静态的,但BigInteger.bitCount()是实例。你的领域模型显然会变得更加复杂,并且存在边界线情况,但总体思路很简单。

答案 9 :(得分:0)

默认情况下我会使用实例方法。优点是可以在子类中覆盖行为,或者如果要对接口进行编码,则可以使用协作者的替代实现。这对于测试代码的灵活性非常有用。

静态引用已添加到您的实现中,无法更改。我发现静态对于短实用方法很有用。如果静态方法的内容非常大,您可能需要考虑将责任分解为一个或多个单独的对象,并让它们与客户端代码协作作为对象实例。

答案 10 :(得分:0)

恕我直言,如果你可以使它成为一个静态方法(不必改变它的结构),那么使它成为一个静态方法。它更快,更简单。

如果您知道要覆盖该方法,我建议您在实际执行此操作时编写单元测试,因此不再适合将其设置为静态。如果这听起来太辛苦了,那就不要把它变成一个实例方法。

一般情况下,您不应该在想象有一天使用时添加功能(这就是疯狂),您应该只添加您确实需要的功能。

更长的解释...

http://en.wikipedia.org/wiki/You_Ain%27t_Gonna_Need_It

http://c2.com/xp/YouArentGonnaNeedIt.html

答案 11 :(得分:0)

静态方法的问题在于,当您与实现相结合时,您正在破坏面向对象的核心原则之一。您希望支持open close原则,并让您的类实现一个描述依赖关系的接口(在行为抽象意义上),然后让您的类依赖于该接口。在此之后,更容易扩展。 ..

答案 12 :(得分:0)

我的静态方法总是以下之一:

  1. 评估仅对该类有用的公式的私有“帮助程序”。
  2. 工厂方法(Foo.getInstance()等)
  3. 在最终的“实用程序”类中,有一个私有构造函数,除了公共静态方法之外什么都不包含(例如com.google.common.collect.Maps
  4. 我不会因为它不引用任何实例变量而将方法设为静态。