web-dev-qa-db-ja.com

「クラスメソッド」と「静的メソッド」の違いは何ですか?

Java、C#、Objective-Cなど、いくつかの異なる言語を使用してきました。

ほとんどの言語では、オブジェクトのインスタンスを必要としないメソッドは静的メソッドと呼ばれます。ただし、Objective-Cに関しては、静的メソッドを呼び出すと防御的な立場になり、クラスメソッドを呼び出すことを期待します。

なぜ静的メソッドではなくクラスメソッドと呼ばれるのですか?静的メソッドとクラスメソッドの違いは何ですか?

33
aryaxt

だから私の質問は、なぜ静的メソッドではなくクラスメソッドと呼ばれるのですか?静的メソッドとクラスメソッドの違いは何ですか?

ウィキペディアから:静的メソッドはクラスのインスタンスを必要とせず、そのようなインスタンスのデータ(またはこれ、自分、私など)に暗黙的にアクセスすることもできません。

これは、Objective-Cのクラスメソッドではないを正確に説明しています。

Objective-Cクラスのメソッドは、メソッド呼び出しのターゲットであるインスタンスを非常に必要とします。つまり、呼び出されるクラスオブジェクトを記述するメタクラスのインスタンスが必要です。

静的メソッドとは異なり、Objective-Cのクラスメソッドは継承できます(前述のselfと組み合わせることで、多くのクラスが+allocの単一の単純な実装をNSObjectは独自のカスタム実装を必要とせずに)、クラスメソッドを呼び出すと、他のメソッド呼び出しサイトとまったく同じobjc_msgSend*ベースのディスパッチメカニズムが実行されます。

Objective-Cのクラスメソッドは、クラス階層全体でオーバーライドでき、スウィズルできます。通常、クラスメソッドの代わりに静的メソッドを提供する言語では、どれもサポートされていません。

結論として、静的メソッドとクラスメソッドは非常に異なるです。その違いは、日々のコーディングの目的ではほとんど透過的ですが、クラスメソッドの動作を知ることで、大量の不要なコード行を節約できる状況がまだあります。

たとえば、静的メソッドではこれを行うことはできません。

@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 ...
}    
72
bbum

クラスメソッドと静的メソッドは実際にはほとんど同じですが、異なります。静的メソッドでは、クラスは名前空間修飾子として機能します。クラスメソッドでは、クラス自体がオブジェクトであるため、クラスメソッドはクラスオブジェクトに対して、インスタンスメソッドはインスタンスに対してまったく同じです。結果として、次のことができます

@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言語の一部です。

4
Nathan Day

静的ではなく動的にバインドされるためです。

これは、実際にはクラスオブジェクトのインスタンスメソッドだからです。

Objective-Cクラスメソッドは、実際にはオブジェクトのクラスオブジェクトのインスタンスメソッドです。

テキストで説明するのは難しいです。こちらの素敵なイラストをご覧ください。

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

4
Eonil

これは純粋に歴史的な違いであり、主にObjective-CがC++と同時に開発され、C++またはそれ以降のJavaおよびC#などの言語が大きな影響力を持っていた。 SmalltalkオブジェクトモデルのCへの移植。その構文と用語は、C++で使用されているものと必ずしも「Cのように」見えるわけではありません。ただし、Objective-Cは、用語「静的メソッド」というのは、その傾向が1983年に確立されていなかったためです。

1
user57368