我已阅读以下讨论:
Should private helper methods be static if they can be static和
Should all methods be static if their class has no member variables
似乎人们通常会接受静态方法,但对此有点怀疑,原因如下:
最可接受的静态方法是私有静态。但那么为什么存在静态方法,在什么情况下它们是首先被采用的?
答案 0 :(得分:58)
静态方法并不难测试。问题是其他代码调用静态方法很难测试,因为你无法替换静态方法。
我认为当静态方法是私有或时它们是“实用”方法 - 例如做字符串转义。当您希望能够在测试中模拟或替换的东西使用静态方法时,问题就出现了。工厂方法也可以有用,虽然依赖注入通常是一种更好的方法 - 再次,它部分取决于您是否希望能够替换测试中的功能。
至于不是“OO” - 并非你用一般OO语言写的所有东西都必须是“纯粹的”OO。有时非OO路线更加实用,导致代码更简单。 Eric Lippert有一篇很棒的博客文章,遗憾的是我现在找不到。但是,this post中的评论是相关的。它讨论的是扩展方法而不是静态方法,但原理是相同的。
扩展方法经常受到批评 因为“不够OOP”。这似乎 让我把车放在前面 这匹马OOP的目的是 为结构提供指导 由...编写的大型软件项目 不需要的团队 知道每个人的内部细节 其他人的工作是为了 生产力。 C#的目的是 一种有用的编程语言 使我们的客户高效工作 在我们的平台上。显然OOP都是 有用和受欢迎,我们已经 因此试图让它变得容易 在C#中以OOP风格编程。但是 C#的目的不是“成为一个OOP 语言“。我们评估基于功能 关于它们是否对我们有用 客户,不是基于他们 严格遵守一些摘要 学术理想是什么造就了 语言面向对象。好 高兴地从oo中获取灵感, 功能性,程序性,命令性, 声明,无论如何,只要我们 可以制作一致,有用的产品 这对我们的客户有利。
答案 1 :(得分:17)
我认为静态方法在函数时肯定是可以的,即它们不执行任何IO,没有任何内部状态,只使用它们的参数来计算它们的返回值。
我还将此扩展到更改其参数状态的方法,但如果这样做过度,静态方法应该是它主要操作的参数类的实例方法。
答案 2 :(得分:5)
想一想。在OO编码中,每个函数调用实际上都是这样的:
method(object this, object arg1, object arg2)
这是您要调用的对象。它真的就是语法糖。此外,它允许您清楚地定义变量的范围,因为您有对象变量等。
静态方法根本就没有“this”参数。即你传入变量并可能得到一个结果。 1.)是人们避开它们的主要原因,你不能创建静态方法的接口(还),所以你不能模拟静态方法来测试它。
其次OO是程序函数等。静态方法在某些情况下很有意义,但它们总是可以成为对象的方法。
请注意,你不能在没有黑客的情况下删除它:
static void Main(string[] args)
{
}
启动应用程序的代码必须可以调用而不引用对象。因此,无论您选择在您的方案中使用它们,都会为您提供灵活性。
答案 3 :(得分:3)
在大多数情况下静态方法很好,单例模式提供了太多的灵活性。
例如,采用一个简单的实用程序,例如将基元提升为幂 - 显然,您根本不需要具有任何多态性。原始值是静态类型,并且数学运算定义良好且不会改变。这并不像你会遇到两个different implementations无法在不重写所有客户端代码的情况下切换它们的情况。
(反讽)
如果只加载一个接口实现,现代JVM非常擅长内联小调用。除非你已经分析了你的代码,并且知道将你的工具发送到接口是一个开销,否则你没有理由不让你的utility methods into an interface可以根据需要改变。
答案 4 :(得分:2)
静态方法的另一个好方案是Factory pattern的实现,您可以在其中以特定方式构造类的实例。
考虑Calendar
类,该类具有一组静态getInstance
方法,每个方法都返回使用所需TimeZone
和/或Locale
或默认值启动的实例。
答案 5 :(得分:1)
我认为静态方法的一个明确例子是当你无法使它们变得动态时,因为你无法修改类。
这对于JDK对象来说是典型的,也是来自外部库的所有对象,以及原始类型。
答案 6 :(得分:1)
我经常使用静态工厂方法代替公共构造函数或与公共构造函数结合使用。
我这样做,当我需要一个构造函数来做一些你不希望构造函数做的事情。即从文件或数据库加载设置。
这种方法还提供了根据它们的作用命名“构造函数”的可能性。当参数本身不足以弄清楚构造函数中发生的情况时,这尤其有用。
Sun在
中使用了这种方法Class.forName("java.lang.Integer");
和
Boolean.valueOf("true");
答案 7 :(得分:1)
首先,你不能忽视静态方法,人们仍然会使用静态方法。
一些设计模式基于静态方法,例如单例:
Config.GetInstance();
辅助函数,假设您有一个字节流,并且您希望函数将其转换为十六进制数字字符串。
静态方法有很多用途,并不是说有些人滥用它太多了(当人们滥用代码时,Code Review是最佳选择)。
答案 8 :(得分:1)
Util类可以是静态的。就像在上面的某些例子中一样,使用转义字符串。当这些utils类执行我们想要模拟的函数时,问题就出现了。例如,apache commons中的FileUtils类 - 通常情况下我想模拟文件交互而不必使用真实文件。如果这是一个实例类,那将很容易。
答案 9 :(得分:1)
重构静态方法要容易得多。它不鼓励对字段成员进行不必要的引用,使耦合变紧。理解调用代码也更容易,因为它显式传递了它与之交互的任何对象。
答案 10 :(得分:0)
通常我会在单个实例正常工作时避免使用静态方法。该单个实例可以实现一个接口,并且可以轻松地进行模拟。我不是说永远不会,但我很少使用静力学。我告诉我的团队他们是否想要使用静态,应该由团队清除。几乎从来都不是我的答案。