何时应该编写静态方法?

24

我明白静态方法或字段的含义,但不确定何时使用它们。也就是说,在编写代码时,哪种设计适合使用静态方法和字段。

一种常见的模式是将静态方法用作静态工厂,但是这同样可以通过重载构造函数来完成。对吗?例如:

var bmp = System.Drawing.Bitmap.LoadFromFile("Image01.jpg");

对于静态字段而言,创建单例对象是它们最好的用法吗?

8个回答

32

静态方法通常用于不需要从类的实例 (this) 中获取任何数据并且可以仅使用它们的参数执行其预期目的的操作。
一个简单的例子是一个方法 Point::distance(Point a, Point b);,它计算两个点之间的距离且不需要实例。

静态字段通常用于所有类实例都要使用的不经常更改的常量等情况下非常有用。


3
那么我们只有在想要访问'this'类的数据成员时才应该创建非静态方法? - GorvGoyl

16
当你使用静态工厂时,它可以更好地表达意图 -- 它还允许您拥有不同的工厂,它们接受相同的参数类型但具有不同的含义。例如,想象一下如果Bitmap有LoadFromResource(string) -- 就不可能有两个构造函数都采用string。 编辑: 来自评论区stevemegson的意见:
静态工厂也可以返回null,并且可以更轻松地返回从缓存中获取的实例。我的许多类都有一个static FromId(int),从主键获取实例,如果我们有现有的缓存实例,则返回它。

9

我认为,当您拥有与实例状态无关的函数时,即不依赖于任何实例字段时,请使用静态方法。

方法所依赖的非局部状态越少,理解起来就越容易,因此static是代码读者的有用信号。


1
如果我理解正确的话,你是在说尽可能使用静态方法。但这感觉不对。在.NET基类库中有很多情况下方法可以是静态的,但它们并不是。 - Chris Smith
1
@wedge - 我同意,今天我在调试一些.NET源代码时感到有些不寒而栗,但也让我对自己写的一些糟糕代码感到更好了 :) - Kev

8
我通过记住实例方法在/内部处理单个对象,而静态方法为类执行某些操作来保持清晰。
在LoadFromFile()的情况下,您需要一个静态方法,因为如果加载失败,则实例尚不存在,您希望得到一个空引用。如果将其实现为构造函数,则必须在失败时抛出异常。
静态方法的其他好用途:对于数据对象,比较(obj a,obj b),删除(obj a)(对象无法删除自身,因为其引用仍然存在),或者用于过程化代码的静态类,这些代码实际上无法在对象中建模。

6
当方法不属于特定对象时,请使用静态方法。
例如,在.NET框架中查看Math类,您会发现所有方法都是静态的。为什么?因为没有理由必须创建一个对象来使用这些方法。当你只想要某个东西的绝对值时,为什么要创建一个Math类的对象呢?没有,没有理由这样做,因此该方法是静态的。
因此,在设计类时,请问自己:
这个方法属于对象还是类本身?
如果该方法修改对象的状态,则该方法属于对象。如果该方法不修改特定对象,则它很可能是静态的。
另一个例子,假设您想知道创建的类的对象数(别问我为什么...)。为此,您可以创建一个静态方法GetNumberOfObjects()(显然需要一个静态字段和一些构造函数中的代码)。你可能会问为什么我要将其设置为静态的。好吧,回答上面的问题,你就会明白。该方法不属于任何特定对象。此外,它不修改任何对象。
希望这有意义。

很棒的示例和回复。 - Xia

2

当您拥有一个不依赖于该类的特定对象的函数时,应使用静态方法。

添加“static”关键字不会造成任何损害:它不会破坏引用它的任何代码。因此,例如以下代码无论是否有“static”关键字都是有效的:

class Foo
{
    public Foo(){}
    public static void bar(){}  // valid with or without 'static'
    public void nonStatic(){ bar(); }
}

...
Foo a = new Foo();
a.bar();

因此,您应该在可能的情况下为所有方法添加“静态”关键字。

1
以下是一些使用静态方法的情况示例:
1)当函数不使用任何成员变量时。您不必在此处使用静态方法,但如果使用通常会更有帮助。
2)在使用工厂方法创建对象时。如果您事先不知道要创建的类型,则它们尤其必要:例如。
class AbstractClass {
    static createObject(int i) {
        if (i==1) {
           return new ConcreteClass1();
        } else if (i==2) {
           return new ConcreteClass2();
        }
     }
}

3) 当您控制或跟踪类的实例化数量时。单例是最常用的示例。

4) 声明常量时。

5) 操作,例如对类的多个对象进行排序或比较,并且不与任何特定实例相关联。

6) 在对象的第一次实例化之前必须进行特殊处理时。


0

当类的客户端没有实例可用时,您可以使用静态方法。例如,单例设计模式用于确保系统中只存在一个类的实例。它要求将单例的构造函数设置为私有,以便客户端无法创建实例。

那么,如果您无法创建实例,如何访问类的实例方法?通过调用返回类的单例实例的静态方法。

当然,这只是一种情况,还有许多其他情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接