2012-06-15 90 views
3

首先,我的代碼:對象 - 子似乎並沒有認識到繼承的選擇

@interface Block : NSObject { 
    NSData *data; 
    NSInteger slice_count; 
} 

@property (readonly) NSData *data; 

+ (Stopwatch *) runOldTestsUsingConfiguration:(TestConfiguration *)c; 

- (Slice *) getSlice:(NSUInteger)idx; 

@end 

- (Slice *) getSlice:(NSUInteger)idx { 
    void *b = (void*)[data bytes] + idx*slice_count; 
    int len = [data length]/slice_count; 
    Slice *ret = [Slice alloc]; 
    [ret initWithBytesNoCopy:b length:len freeWhenDone:NO]; 
    return ret; 
    //NSString *temp2 = [data description]; 
    //NSRange r = NSMakeRange(idx*slice_count, [data length]/slice_count); 
    //NSData *d = [data subdataWithRange:r]; 
    //NSString *temp = [d description]; 
    //Slice *s = [[Slice alloc] initWithBytesNoCopy:(void *)[d bytes] length:r.length freeWhenDone:NO]; 
    //return s; 
} 

其中SliceNSData一個簡單的子類。

出於某種原因,我得到一個運行時錯誤,似乎表明我的Slice實例或者a)實際上不是一個具體實例(?)或b)其繼承中出現問題,並且消息isn沒有把自己綁定到Slice上(幾乎可以肯定的是,我還沒有發現錯誤)。

我得到確切的錯誤是這樣的:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** 
initialization method -initWithBytes:length:copy:freeWhenDone:bytesAreVM: 
cannot be sent to an abstract object of class Slice: Create a concrete instance!' 

誰能幫助我嗎?我已經嘗試過所有我能想到的東西(其中的基本例程在消息調用本身中有詳細說明),而且我仍然在乾涸。當它說'創建一個具體實例'是什麼意思?是不是我在做什麼,當我alloc呢?

+0

分裂的'alloc' /'init'差可可風格(尤其是不需要重新分配),不應該在任何不屬於你的類上完成(因爲你不能確定'init'不會拋棄它傳遞的對象並返回一個新對象) 。 –

+0

見下文;那時我不關心風格。這是我多年來採用的調試技術。我知道這樣做的危險,但是在那個時候,我可以想到的其他事情並不多。 –

回答

4

子類化NSData比你想象的要複雜得多。在大多數情況下,你最好只是圍繞NSData編寫一個包裝,而不是完整的子類。

+0

爲什麼寫一個包裝給我的結果不同於編寫「完整的子類」?面向對象的語言通常對於那些事情是非常一致的(至少我真的很熟悉,其中我承認ObjC還不是成員) –

+1

@vermiculus NSData可能並不是你期望的那樣,因爲它是隱藏的類集羣的一部分。這就是爲什麼對它進行子類化並不像你期望的那樣工作的原因。如果你包裝它,那麼你沒有公開NSData的實現細節。你可以在[這個答案]中閱讀更多信息(http://stackoverflow.com/a/5772610/608157) –

+0

@vermiculus它的簡短版本是當你調用'[[NSData alloc] initWithBytes的時候。 ..];'它返回一個被認爲是「NSData」的「具體實現」的子類。如果你真的想完成「NSData」的完整子類化,那麼你需要實現其他幾種方法,以便按照你期望的方式工作。 –

1

IIRC,init方法被允許重新分配self,因此應始終與alloc一樣使用在同一行上。

Slice *ret = [[Slice alloc] initWithBytesNoCopy:b length:len freeWhenDone:NO]; 

我不確定這是否是根本原因,但是這對我來說是一個紅旗,可能導致您朝着良好的方向發展。

編輯:

事實上,它有我想,如果你已經在你的子類覆蓋+ alloc和沒有返回一個實例...

+0

這很可能不是問題。儘管如此,還是值得指出的,但它應該是一個評論。 –

+0

'Slice'只引入一個實例變量和一個方法,它不是一個繼承的方法。在絕望的時候,我傾向於分解表達式並逐行瀏覽它們:P謝謝,但我認爲這也不是問題。 :P –

相關問題