简体   繁体   English

在什么情况下静态方法是一个好习惯?

[英]In what situations is static method a good practice?

I have read the following discussions: 我看过以下讨论:

Should private helper methods be static if they can be static , and 如果私有帮助方法可以是静态的那么它们应该是静态的吗?
Should all methods be static if their class has no member variables 如果它们的类没有成员变量,那么所有方法都应该是静态的

It seems that people in general would accept static methods, but are a little bit skeptical about it, for the following 2 reasons: 似乎人们通常会接受静态方法,但对此有点怀疑,原因如下:

  1. They are hard to test. 他们很难测试。
  2. They violate the OO principle. 他们违反了OO原则。 (They are functions, not methods, said a person.) (一个人说,它们是功能,而不是方法。)

And the most acceptable static methods are private static ones. 最可接受的静态方法是私有静态方法。 But then why do static methods exist at all, and in what situations they are the first priority to be adopted? 但那么为什么存在静态方法,在什么情况下它们是首先被采用的?

Static methods aren't hard to test in and of themselves. 静态方法并不难测试。 The problem is that other code calling the static method is hard to test, because you can't replace the static methods. 问题是调用静态方法的其他代码很难测试,因为你无法替换静态方法。

I think static methods are fine either when they're private or when they're "utility" methods - eg to do string escaping. 我认为静态的方法都很好既可以当它们是私有的, 或者当他们是“实用”的方法-例如,做串逃跑。 The problem comes when you use static methods for things that you want to be able to mock out or otherwise replace within tests. 当您希望能够在测试中模拟或替换的东西使用静态方法时,问题就出现了。 Factory methods can be useful too, although dependency injection is generally a better approach - again, it partly depends on whether you want to be able to replace the functionality in tests. 工厂方法很有用,虽然依赖注入通常是一种更好的方法 - 再次,它部分取决于您是否希望能够替换测试中的功能。

As for not being "OO" - not everything you write in a generally OO language has to be "pure" OO. 至于不是“OO” - 并非你用一般OO语言写的所有东西都必须是“纯粹的”OO。 Sometimes the non-OO route is simply more pragmatic and leads to simpler code. 有时非OO路线更加实用,导致代码更简单。 Eric Lippert has a great blog post about this, which unfortunately I can't find right now. Eric Lippert有一篇很棒的博客文章,遗憾的是我现在找不到。 However, there's a comment in this post which is relevant. 但是, 这篇文章中的评论是相关的。 It talks about extension methods rather than static methods, but the principle is the same. 它讨论的是扩展方法而不是静态方法,但原理是相同的。

Extension methods are often criticized as being "not OOP enough". 扩展方法经常被批评为“不够OOP”。 This seems to me to be putting the cart in front of the horse. 在我看来,这是把车放在马前。 The purpose of OOP is to provide guidelines for the structuring of large software projects written by teams of people who do not need to know the internal details of each other's work in order to be productive. OOP的目的是为大型软件项目的结构提供指导,这些项目由不需要了解彼此工作的内部细节以便提高工作效率的团队编写。 The purpose of C# is to be a useful programming language that enables our customers to be productive on our platforms. C#的目的是成为一种有用的编程语言,使我们的客户能够在我们的平台上高效工作。 Clearly OOP is both useful and popular, and we've therefore tried to make it easy to program in an OOP style in C#. 显然,OOP既有用又受欢迎,因此我们试图在C#中以OOP风格进行编程。 But the purpose of C# is not "to be an OOP language". 但是C#的目的不是“成为OOP语言”。 We evaluate features based on whether they are useful to our customers, not based on whether they conform strictly to some abstract academic ideal of what makes a language object-oriented. 我们根据它们是否对我们的客户有用来评估特征,而不是基于它们是否严格符合某些语言面向对象的抽象学术理想。 We'll happily take ideas from oo, functional, procedural, imperative, declarative, whatever, so long as we can make a consistent, useful product that benefits our customers. 我们很乐意从oo,功能,程序,命令,声明等方面获取想法,只要我们能够制造出有益于我们客户的一致,有用的产品。

I'd say that static methods are definitely OK when they are functions , ie they don't do any IO, don't have any internal state and only use their parameters to compute their return value. 我会说静态方法在它们是函数时肯定是可以的 ,即它们不做任何IO,没有任何内部状态,只使用它们的参数来计算它们的返回值。

I'd also extend this to methods that change the state of their parameters, though if this is done excessively, the static method should properly be an instance method of the parameter class that it mainly operates on. 我还将它扩展到改变其参数状态的方法,但如果这样做过度,静态方法应该正确地是它主要操作的参数类的实例方法。

Think of this for a moment. 想一想这一点。 In OO coding, every single function call actually looks like this: 在OO编码中,每个函数调用实际上都是这样的:

method(object this, object arg1, object arg2) where this is the object you are calling. method(object this, object arg1, object arg2)这是你要调用的对象。 All it really is is syntax sugar for this. 它真的就是语法糖。 Additionally it allows you to clearly define scope of variables because you have object variables etc. 此外,它允许您清楚地定义变量的范围,因为您有对象变量等。

Static methods simply don't have a "this" parameter. 静态方法根本没有“this”参数。 Ie you pass variables in and possibly get a result back out. 即你传入变量并可能得到一个结果。 1.) is the main reason people avoid them, you can't create an interface to a static method (yet) so you can't mock out the static method to test it. 1.)是人们避开它们的主要原因,你不能创建静态方法的接口(还),所以你不能模拟静态方法来测试它。

Secondly OO are procedures functions etc. Static methods make a lot of sense in certain situations, but they can always be made into a method on an object. 其次OO是程序函数等。静态方法在某些情况下很有意义,但它们总是可以成为对象的方法。

Mind you, you couldn't remove this without a hack: 请注意,你不能在没有黑客的情况下删除它:

static void Main(string[] args)
{
}

The code that starts your application MUST be callable WITHOUT a reference to an object. 启动应用程序的代码必须是可调用的,不带对象的引用。 So they give you flexibility, whether you choose to use them in your scenario will be predicated by your requirements. 因此,它们为您提供了灵活性,无论您选择在您的方案中使用它们都将根据您的要求进行预测。

Static methods are fine in most situations where the singleton pattern gives too much flexibility. 在单例模式提供过多灵活性的大多数情况下,静态方法都很好。

For example, take a simple utility such as raising a primitive to a power - obviously you never need to have any polymorphism in that. 例如,采用一个简单的实用程序,例如将原语提升为幂 - 显然,您永远不需要具有任何多态性。 Primitive values are of static type and mathematical operations are well defined and don't change. 原始值是静态类型,并且数学运算定义良好且不会改变。 It's not like you'll ever get the situation of having two different implementations an no way of switching between them without rewriting all your client code. 这并不像你会得到两种不同 实现的情况,无法在不重写所有客户端代码的情况下切换它们。


(irony off ) (反讽)

Modern JVMs are pretty good at inlining small calls if only one implementation of an interface is loaded. 如果只加载一个接口实现,现代JVM非常擅长内联小调用。 Unless you have profiled your code and know dispatching your utilities to an interface is an overhead, you've no excuse for not making your utility methods into an interface which can be varied if required. 除非您已经分析了代码并且知道将实用程序分派给接口是一种开销,否则您没有理由不将实用程序方法放入可以根据需要改变的接口中。

I think a definite case for static methods is when you cannot make them dynamic, because you cannot modify the class . 我认为静态方法的一个明确情况是当你不能使它们变得动态时,因为你无法修改类

This is typical for JDK objects, and also all objects coming from external libraries, and also primitive types . 对于JDK对象来说典型的,也是来自外部库的所有对象,也是原始类型

Another good scenario for static methods are implementations of the Factory pattern , where you are allowing for instances of a class to be constructed in a specific manner. 静态方法的另一个好方法是Factory模式的实现 ,您可以在其中以特定方式构造类的实例。

Consider the Calendar class, which has a set of static getInstance methods, each returning instances primed with the desired TimeZone and/or Locale or the default. 考虑Calendar类,它有一组静态getInstance方法,每个方法都返回使用所需TimeZone和/或Locale或默认值准备TimeZone实例。

I often use static factory methods instead of or in conjunction with public constructors. 我经常使用静态工厂方法代替公共构造函数或与公共构造函数结合使用。

I do this, when i need a constructor that does something you would not expect a constructor to do. 我这样做,当我需要一个构造函数来做一些你不希望构造函数做的事情。 Ie load settings from a file or database. 即从文件或数据库加载设置。

This approach also provides the possibility of naming the "constructors", based on what they do. 这种方法还提供了根据它们的作用命名“构造函数”的可能性。 This is especially useful, when the parameters themselves are not enough to figure out what happens in a constructor. 当参数本身不足以弄清楚构造函数中发生的情况时,这尤其有用。

Sun uses this approach in Sun使用这种方法

Class.forName("java.lang.Integer");

and

Boolean.valueOf("true");

It's much easier to refactor methods that are static. 重构静态方法要容易得多。 It discourages unnecessary references to field members that make the coupling tight. 它不鼓励对字段成员进行不必要的引用,使耦合变紧。 It's also easier to understand calling code because it explicitly passes any objects it interacts with. 理解调用代码也更容易,因为它显式传递了它与之交互的任何对象。

First of all, you can't dismiss static-methods there is a reason people still use it. 首先,你不能忽视静态方法,人们仍然使用它。

  1. some design patterns are based on static methods, singleton for example: 一些设计模式基于静态方法,例如:

    Config.GetInstance(); Config.GetInstance();

  2. Helper functions, lets say you have a byte-stream and you want a function to convert it into a string of Hex numbers. 辅助函数,假设您有一个字节流,并且您希望函数将其转换为十六进制数字串。

there are many uses for static-methods, saying that does not mean that some people abuse it too much(Code Review is best option when people abuse code). 静态方法有很多用途,并不是说有些人滥用它太多了(当人们滥用代码时,Code Review是最好的选择)。

Util classes can be OK to be static. Util类可以是静态的。 As in someone elses example above, with escaping strings. 就像在上面的某些例子中一样,使用转义字符串。 The problem lies when those utils classes perform functions that we would want to mock. 当这些utils类执行我们想要模拟的函数时,问题就出现了。 For example, the FileUtils class in apache commons - it is often the case that I want to mock file interactions without having to play with real files. 例如,apache commons中的FileUtils类 - 通常情况下我想模拟文件交互而不必使用真实文件。 If this was an instance class, it would be easy. 如果这是一个实例类,那将很容易。

Generally I avoid static methods when a single instance will work fine. 通常,当单个实例工作正常时,我会避免使用静态方法。 That single instance can implement an interface and can be mocked easily. 该单个实例可以实现一个接口,并且可以轻松地进行模拟。 I'm not saying never but I rarely use statics. 我不是说永远不会,但我很少使用静力学。 I tell my team if they want to use a static it should be cleared by the team. 我告诉我的团队他们是否想要使用静态,应该由团队清除。 Almost never is my answer. 几乎从来不是我的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在可能的良好实践中声明一个方法是静态的吗? - Is declaring a method static when possible good practice? 使用静态方法从另一个活动开始活动是一个好习惯吗? - Is it a good practice to start activity using static method from another activity? 这是通过一个静态方法访问最终类的好习惯吗? - Is this a good practice to access a final class with one static method? 拥有90%静态成员的Java类。 好的做法还是什么? - Java Class That Has 90% Static Members. Good Practice Or What? java中方法的好习惯 - Good practice for method in java 使用静态初始化器是一个好习惯吗? - Is it a good practice to use static initializers? 静态初始化是良好的编程实践吗? - Is Static Initialization Good Programming Practice? 什么是好习惯? 复制构造函数或防御性复制方法 - What is good practice? A copy constructor or a defensive copy method 用Java创建输入验证方法的良好实践是什么? - What's good practice of creating input validation method in Java? 在静态方法中使用非静态变量或调用非静态方法(使用对象实例进行访问)是一种好习惯吗? - Is it a good practice to use non-static variables or invoke a non-static method (access using the object instance) within the static method?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM