2011-10-16 10 views
1

編集:問題解決済み!クリーニングしてリブートした後、ただ消えた!私はこの原因を知りません!Xcode4の新しいLLVMコンパイラはクラスの継承を正しく機能させませんか?

は、これが今の私に完全な一日のために頭痛を引き起こした:Xcodeの3.2のすべてで

は優秀働きました。それから私は4.2に切り替えました。突然、クラス継承はもう働きません。

私はクラスTheSuperclassTheSubclass : TheSuperclassを持っています。テストを簡単にするために、私は実際にこのように作成しました。

// TheSuperclass.h 
@interface TheSuperclass : NSObject { 

} 

// subclasses must override this method 
- (id)returnSomethingUseful; 

@end 

// TheSuperclass.m 
#import "TheSuperclass.h" 

@implementation TheSuperclass 
- (id)returnSomethingUseful { 
    NSLog(@"Dude, you have to override -returnSomethingUseful"); 
    return nil; // subclasses override this method! 
} 


- (id)init { 
    if ((self = [super init])) { 
      obj = [self returnSomethingUseful]; // TEST 
     NSLog(@"TheSuperclass initialized: %@", obj); 
    } 
    return self; 
} 
@end 

// TheSubclass.h 
#import "TheSuperclass.h" 

@interface TheSubclass : TheSuperclass { 

} 

@end 

// TheSubclass.h 
#import "TheSubclass.h" 

- (id)returnSomethingUseful { 
    NSLog(@"Correct method called!"); 
    return usefulObject; 
} 

TheSubclass *foo = [[TheSubclass alloc] init]; // remember: init of superclass calls the method 
// Getting the NSLog: "Dude, you have to override -returnSomethingUseful" 


id bar = [foo returnSomethingUseful]; // now call it directly on foo 
// Getting the NSLog: "Correct method called!" 

:あなたがここに見ることができるものよりも多くのコードはありません

は、つまり、テンプレートメソッドを宣言だけで、何もしないnilを返し、サブクラス化のために意図されているメソッド:

- (id)returnSomethingUseful { 
    NSLog(@"Dude, you have to override -returnSomethingUseful"); 
    return nil; // subclasses override this method! 
} 

TheSubclassでは、私は単純にそのテンプレートメソッドをオーバーライドします。もちろん、私はTheSuperclassの実装をコピーして100%正しくしました。タイプミスはありません。それは確認された事実です。 TheSuperclassの実装では

- (id)returnSomethingUseful { 
    NSLog(@"Correct method called!"); 
    return usefulObject; 
} 

コードの一部は、テンプレートメソッドからそのオブジェクトを取得するために[self returnSomethingUseful]を呼び出します。このようになります。それは素晴らしいパターンであり、私はそれをたくさん使ってきました。それは常にこのように正確に働いた。

しかし、私はTheSubclassのインスタンスを作成しても、常にWRONGメソッドを呼び出すように見えます。 TheSuperclassのものではなく、TheSuperclassからのものです(これはもちろん超過方法です)

私はそれを少なくとも100回チェックしました!真剣に、それはTheSubclassのインスタンスです。それは私にNSLogsを与えるTheSuperclassのinitメソッドを呼び出します。

今は本当に奇妙な部分:

TheSubclass *foo = [[TheSubclass alloc] init]; 
id bar = [foo returnSomethingUseful]; 
// Getting the NSLog: "Correct method called!" 

をので、それを強調するために:私はそれが動作しますが、「外部から」私のTheSubclassオブジェクトにそのメソッドを呼び出して、私はTheSuperclassの実装内から[self returnSomethingUseful]を呼び出すと、

これを回避するにはどうすればよいのでしょうか?これはランタイムで問題になるのですか?これは、おそらくコンパイラのエラーによって引き起こされるでしょうか?

+1

きれいにして再構築しますか?コンパイラがアップグレードから二日酔いを取得している可能性があります。 NSLogの代わりにブレークポイントを使用することを検討してください。 – BoltClock

+1

私は1つ設定するたびに私がお金を稼ぐように使用されるブレークポイント。それは、必要なときに優先メソッドにジャンプしません。 – dontWatchMyProfile

+0

"これはWRONGの実装を呼び出します"これは、あなたが '+ [TheSubclass init]'の実装を示すべき理由です。実際に、TheSubclassのインスタンスではありません。 – Caleb

答えて

4

LLVMは明らかに簡単なサブクラス化を正しく実装できます。何千ものプログラムが毎日それを使用しているので、標準的なコードを書いているならば、これは問題ではありません。ここにあなたがすべきことがあります:

  • リブート。 Xcodeは、インストール後に再起動する必要がないと主張します。あなたは私の経験でやっています。 Xcodeをアップグレードした後、90%の問題を解決します。
  • 清掃して再構築してください。 3.2から4.2への移行は、導出されたファイルを完全に異なる場所に配置するため、これを修正する可能性は低くなります。しかし、それは試してみる価値があります。
  • [self class]をチェックして、自分が本当にあなたの考えであることを確認してください。
  • isaポインター(決して見つけにくい;あなたのコードで->isaを検索する)を決して乱さないことを確認してください。
  • initを確認してください。これは、あまりにも厄介なことをした可能性が最も高い場所です。シンプルなパターンに従っていることを確認してください。
  • 最も簡単な形式の問題を抽出し、それを示すコードを投稿してください。あなたの説明から、これは非常に少数のコード行で行うことができるはずです。この単純化されたバージョンを作成しようとすると、間違いがどこにあるかを示すよりも頻繁に表示されます。
+0

ありがとうRob。私はこれらのことを試してみる。ファンシーな部分について:私がしたことは、私の更新された質問の上です。方法はうごめき、トリックはありません。 – dontWatchMyProfile

+0

クリーニング、再起動、再構築後に問題は消えました! – dontWatchMyProfile

1

用語は「上書き」であり、「上書き」ではありません。

問題の内容を把握するのに十分なコードが表示されていません。両方のクラスの-initメソッドを表示し、サブクラスのインスタンスがどこに作成されているかを表示します。

+0

何が必要ですか? – dontWatchMyProfile

+0

btw、言い回しの訂正のおかげで。私は常に上書きを上書きと混同します。英語のネイティブスピーカーではありません。 – dontWatchMyProfile

+0

コメントはどのようにして2つのアップボックスを得るのですか? – JustSid

2

コンパイラが何かそんなに基本的なことを犯したら、システムは起動しません。

TheSuperclassのインスタンスがあるか、またはスペルが間違っているため、initメソッドでクラスをアサートしてください。