关于C#:”类方法”和”静态方法”有什么区别?

What's the difference between “class method” and “static method”?

我使用了几种不同的语言,如Java、C语言和Objtovi-C。

在大多数语言中,不需要对象实例的方法称为静态方法。然而,当涉及到Objective-C时,有些人在您调用静态方法时会受到防御,他们希望您调用它们类方法。

为什么它们被称为类方法而不是静态方法?静态方法和类方法有什么区别?


So my question is why are they called class methods instead of a
static method? What is the difference between a static method and a
class method?

来自维基百科:静态方法既不需要类的实例,也不能隐式地访问此类实例的数据(或this、self、me等)。

这正好描述了什么是Objective-C的类方法不是。

Objective-C类方法非常需要一个作为方法调用目标的实例。也就是说,它需要一个描述被调用的类对象的元类实例。

与静态方法不同,Objective-C的类方法可以被继承(与前面提到的self相结合,这正是许多类可以在NSObject上共享一个简单的+alloc实现而不需要自己的自定义实现的原因),并且调用一个类方法也经历了完全相同的过程。与其他方法调用站点一样,基于docx1〔3〕的调度机制。

Objective-C的类方法可以在整个类层次结构中被重写,并且可以被改写。通常提供静态方法代替类方法的语言不支持这些方法。

归根结底,静态方法和类方法是非常不同的。虽然这种差异对于日常编码来说是透明的,但是在某些情况下,了解类方法的工作方式可以为您节省大量不必要的代码行。

例如,不能使用静态方法执行此操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@interface AbstractClass:NSObject
+ factory;
@end

@implementation AbstractClass
+ factory
{
    return [[[self alloc] init] autorelease];
}
@end

@interface Concrete1:AbstractClass
@end
@implementation Concrete1
@end
@interface Concrete2:AbstractClass
@end
@implementation Concrete2
@end

void foo() {
    Concrete1 *c = [Concrete1 factory];
    Concrete2 *d = [Concrete2 factory];
    ... etc ...
}


因为它是动态绑定的,而不是静态的。

因为它实际上是类对象的实例方法。

Objective-C类方法实际上是一个对象的类对象的实例方法。

很难用文字来描述。请看这里的插图。

http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_classes_and_metaclasses.html


虽然类方法和静态方法在实践中大多数时候是相同的,但它们是不同的。对于静态方法,类充当命名空间限定符。对于类方法,类本身是一个对象,因此类方法对类对象的作用与实例方法对实例的作用完全相同;因此,可以执行以下操作

1
2
3
4
5
6
7
8
9
10
11
@interface TestClass : NSObject
+ (void)classOrInstanceMethod;
- (void)classOrInstanceMethod;
@end
...
NSArray * arr = [NSArray arrayWithObjects:
                        [[[TestClass alloc] init] autorelease],
                        [TestClass class],
                        nil];
for( id obj in arr )
    [obj classOrInstanceMethod];

调用ClassorInstanceMethod的哪个版本取决于obj是类对象还是实例。如果您熟悉工厂类模式,则此模式是Objective-C语言的一部分。


这纯粹是一个历史的差异,主要源于Objto-C与C++同时开发的事实,以及在C++或更高的语言如Java和C语言之前有很大的影响。Objest-C本质上是SimultTalk对象模型到C的一个端口,因此它的语法和术语不一定看起来像C++所用的"C类"。然而,客观-C决不能通过不使用"静态方法"来逆势而行,因为在1983年,这种趋势还没有得到很好的证实。