2011-12-01 7 views
7

[NSMutableString stringWithString:@ ""]はなぜ機能しますか?

NSStringには、+stringWithString:という静的メソッドがあります。 これはNSMutableStringに再宣言/上書きされないので、NSMutableStringを返すとは仮定できません。実際にも、NSStringのクラスで戻り値の型はiddoc states次のように定義されます

戻り値は
aStringから文字をコピーして作成された文字列を。

これがなぜ機能し、返品するのか私の知るところでは、私は何が分かりませんでしたかNSMutableString?特に、基底クラスNSStringは、変更可能な文字列が必要であることを認識していないためです。

一つは、内部[Class alloc]がタイプNSMutableStringのオブジェクトを生成しますどのと呼ばれていることを言うことができるが、私たちは、ソースコードを持っていないとstringWithString:が、それは内部的に欲しいものは何でもできても、これは純粋な推測です。

これらのクラスメソッドはすべてサブクラスで再実装されていますか?そしてもしそうなら、なぜこれは文書化されていないのですか?

答えて

6

NSStringには、+ stringWithString:という静的メソッドがあります。

もっと正確には、クラスメソッドです。

これは、ココアでNSMutableString

でオーバーライド/再宣言されていない、サブクラス再宣言する方法を必要としません。実際、それはちょうど多くのノイズ(IMO)を生成します。それはを定義するだけで、そのカスタム実装を提供するメソッドを再定義する必要があります。

これはNSMutableStringを返すとは想定できません。

は、可変文字列を返す必要があると仮定します。サブクラスは、メソッドを公に再宣言することなく必要なコントラクトを満たすために、必要に応じてイニシャライザとコンシューマコンストラクタを再定義することができます。ベースの実装が不十分な場合にのみメソッドを定義する必要があります。

これがなぜ動作してNSMutableStringを返すのか理解するために、私の知るところでは何が分かりませんか?特にベースクラスNSStringは、変更可能な文字列が必要であることを認識していないためです。

[NSString stringWithString:@"bah"]ではなく[NSMutableString stringWithString:@"bah"]と書かれているため、「分かっています」。インスタンスメソッドと同様に、クラスメソッドは暗黙的にselfを持ち、クラスメソッドを通して型を渡すことができます。したがって、クラスメソッドは必要に応じて再定義/オーバーライドできます。クラスメソッドは、その型を決定またはメッセージするためにselfを使用することもできます(まもなく例)。

一つは、内部で[クラスのalloc]はタイプNSMutableStringのオブジェクトを生成しますこれと呼ばれますが、でもこれは、我々はソースコードとstringWithStringを持っていないとして、純粋な推測であると言うことができる:それは内部的に欲しいものは何でも行うことができます。

これは推測ではありません。この場合、が不変の文字列を返した場合は、バグを報告する必要があります。それ以外の場合は、1つ以上の定義を使用したかどうかにかかわらず、広告として動作します。

これらのクラスメソッドはすべてサブクラスで再実装されていますか?コンビニエンスコンストラクタの場合

、それは指定された初期化子のうちの1つを介して行くことがより一般的です:例外は頻繁に行うことができるが、

@implementation NSString 
+ (id)stringWithString:(NSString *)arg 
{ 
    // self is either +NSString or +NSMutableString 
    return [[[self alloc] initWithString:arg] autorelease]; 
} 

ような実装は次の形式を取ることができます多くの場合、最適化された不変/変更可能な型の場合があります。

@implementation NSString 
+ (id)stringWithString:(NSString *)arg 
{ 
    return [arg imp_isMutable] ? [[[self alloc] initWithString:arg] autorelease] : arg; 
} 
... 
@implementation NSMutableString 
+ (id)stringWithString:(NSString *)arg 
{ 
    return [[[self alloc] initWithString:arg] autorelease]; 
} 
... 

もしそうなら、これはなぜ文書化されていないのですか?

彼らは、基本クラスまたは特別なノートからいくつかの偏差を持っていない限り、唯一の違いは、あなたが要求したクラス型の場合に再宣言またはredocumentedすべきではない - その場合でも、それが良いだろう別の名前のメソッドを作成します。 NSStringので

+0

私はあなたが私の仮定の一部( "自己"についての部分)を繰り返していると思いますが、それは矛盾した結果を返すためにすべてのクラスメソッドをサブクラスで再実装しなければならないということです。 。したがって、実装されていないので基本クラスのメソッドがNSStringを返すことは技術的に可能ですが、サブクラスが特別な機能を持つスーパークラスの完全な実装であり、バグ。ありがとう! –

+1

@Jorisまあまあです。クラスメソッドが典型的なパターンで実装されている場合、サブクラスはクラスメソッドをオーバーライドする必要はありません。私。もし '+ stringWithString:'が 'return [[self alloc] initWithString:...] autorelease];として実装されていれば、NSMutableStringがそのメソッドをオーバーライドする必要はありません(' -initWithString : '代わりにインスタンスメソッド。 – bbum

+0

はい、ベースクラスがどのように実装されており、一貫性を保っているか分かっていれば、明らかにそれを再実装する必要はありません。それは理にかなっている。 –

3

NSMutableStringNSStringのサブクラスであるため、NSMutableStringで呼び出されるメソッドはすべて適切に動作し、意味がある場合はNSMutableStringを返します。慣れていないインスタンスを返すcopyですが、それに従わない唯一の方法があります。

これは、具体的なインスタンスではなくidを返し、すべてのクラスメソッドが[MYActualClass alloc]の代わりに[self alloc]を使用する理由です。

3

あなたは少しこのように初期化子を書くことができます:あなたは、NSStringにこの初期化子を呼び出す[self alloc]戻りNSString、あなたがNSStringバックのインスタンスを取得するときに今

+ (id) stringWithString: (NSString*) foo 
{ 
    return [[self alloc] initWithString:foo]; 
} 

。しかし、[NSMutableString stringWithString:@"…"]を呼び出すと、[self alloc]メッセージの結果はNSMutableStringになるため、イニシャライザは可変文字列を返します。

+0

これはメモリリークを引き起こす可能性があります。メソッド名 'stringWithString:' [implies](https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html#//apple_ref/doc/uid/TP40008195- CH27-SW3)、返されたオブジェクトの所有権は受信者に転送されません。 –

+0

これはARCの前に書かれたものだと思うので、それは本当にリークでしたが、ARCでは今日は期待通りに動作します。 – zoul

+0

あなたはまだ良いメモリ管理を練習しなければなりません... –

3
(ジャスティンが言ったことが、明確化)

+ stringWithStringという静的メソッドがあります:。この はNSMutableStringで再宣言/オーバーライドされないため、 はNSMutableStringを返すとは仮定できません。でも、NSStringの クラスで実際には戻り値の型は... IDとして

最初に定義されており、何よりも、のObjective-Cは、静的メソッドを持っていません。 Objective-Cのクラスメソッドはです。クラスメソッドは、インスタンスメソッド(クラスがメタクラスのインスタンスである)と全く同じように動作し、継承、オーバーライドなどが可能です。

したがって、正確にNSMutableStringcharacterAtIndex:を継承し、必要な場合は、NSMutableStringはクラスメソッドでも同じことができます。

スーパークラスからオーバーライドされたヘッダーにメソッドを宣言する必要はありません。オーバーライドされたメソッドは親として正確に動作するが、サブクラスの要件のコンテキスト内で動作するようにオーバーライドされるため、フレームワーク内のクラスは一般的にであり、は明示的に宣言しません。

関連する問題