[英]ARC and Objective C Subclassing
我對Obj C和iOS開發很陌生,遇到了一個我不了解為什么會發生的問題。
因此,要設置場景,我有2個模型類,播放器和計算機播放器以及一個控制器。
玩家:
@interface Player : NSObject
-(void) playerMessage;
@end
ComputerPlayer:
@interface ComputerPlayer : Player
-(void) computerPlayerOnlyMessage;
@end
控制器:
@interface viewController : UIViewController{
Player *p1;
Player *p2;
Player *currentPlayer;
}
@implmentation ViewController
-(void)viewDidLoad
{
p1 = [[Player alloc]init];
p2 = [[ComputerPlayer alloc]init];
[p1 playerMessage];
currentPlayer = p2;
[currentPlayer computerPlayerOnlyMessage];
}
但是,以上問題是[currentPlayer computerPlayerOnlyMessage]打開ARC時出現編譯錯誤。 當ARC關閉時,它會發出編譯器警告,但也會像我期望的那樣運行。
感謝您提供任何幫助,以幫助我弄清楚為什么會發生這種情況。
定義是否更好:
- (void)playerMessage;
ComputerPlayer
類中的方法,並且:
-(void)playerMessage {
[super playerMessage];
[self computerOnlyPlayerMessage];
}
那是inheritance
點,不是嗎? 您將類變量定義(期望)為Player
但未定義ComputerPlayer
,如果為ComputerPlayer
,它將僅對“ computer”執行特定的工作。
當然,然后執行:
[Player playerMessage]; // Warning should gone
ps:請投下反對票的人解釋原因,並給與他們一個機會
您可以測試它是否是計算機播放器
if ([currentPlayer isKindOfClass:[ComputerPlayer class]])
[(ComputerPlayer *)currentPlayer computerPlayerOnlyMessage];
它給您一個錯誤,因為p2是Player的子類,並且在Player類中沒有諸如computerPlayerOnlyMessage這樣的方法。 此方法存在於ComputerPlayer類中,因此您應將p2聲明為該類型的對象。 在您聲明p2的chenge行中:
ComputerPlayer *p2;
首先,不要像聲明一樣聲明它們
@interface viewController : UIViewController{
Player *p1;
Player *p2;
Player *currentPlayer;
}
用@properties
做到這一點。 原因是ivars沒有任何getter或setter,而如果您使用'@properties
@properties,它們將自動生成。
@interface viewController : UIViewController
// This will auto generate the ivars, getters and setters
@property (nonatomic, strong) Player *p1;
@property (nonatomic, strong) Player *p2;
@property (nonatomic, strong) Player *currentPlayer;
@end
那你就可以
@implmentation ViewController
-(void)viewDidLoad
{
p1 = [[Player alloc]init];
p2 = [[ComputerPlayer alloc]init];
[p1 playerMessage];
currentPlayer = p2;
// Could also replace below with [currentPlayer isKindOfClass:[ComputerPlayer class]] use which ever fits best for you and what you want.
// If using below, if you decided to subclass ComputerPlayer class anything that subclassed
// from ComputerPlayer will also make it into this if statement. If iskindOfClass: is used
// Only objects that are kind of class will make it into this if statement.
if([[currentPlayer class] isSubclassOfClass:[ComputerPlayer class]]) {
[(ComputerPlayer *)currentPlayer computerPlayerOnlyMessage];
}
}
正如@Greg所說, computerPlayerOnlyMessage
是ComputerPlayer
類(而不是其繼承的類)公開的方法,因此即使在禁用ARC的情況下編譯器報告警告,使用它也是一種不好的做法。
明確詢問類實例是否實現了該方法,但這是一種可行的解決方法。 但是我認為解決方案缺乏良好的OO設計,除非有充分的理由(在某些情況下它很方便),否則我不會使用它-在其他OO語言中是不可能的。
多態允許類的實例被當作其超類之一使用,但不能相反。 您可以覆蓋和專門化超類方法,但是您不能期望超類知道其任何子類實現的方法。
我建議兩種可能的解決方案:
Player
類中的computerPlayerOnlyMessage
聲明為抽象(帶有空主體或引發異常,以提醒應在子類中重寫該方法) ComputerPlayer
刪除computerPlayerOnlyMessage
,而是重寫playerMessage
。 由於多態性,無論您是以Player
還是ComputerPlayer
身份訪問類實例,都將調用正確的實現。 如果computerPlayerOnlyMessage
打算做playerMessage
工作,只是以一種不同的方式,我會選擇選項no。 2
這似乎是使用協議的好地方。
這就是我編寫示例的方式,在該示例中,我需要向所有Player實例發送“玩家”消息,有時需要專門化,而在其他時間發送特定的“ npc”消息。
@protocol <NPC>
@property (nonatomic) NSString *someNPCString;
- (void)foo;
- (void)bar;
@end
@interface Player : NSObject
@end
@implementation Player
- (void)message
{
NSLog(@"message");
}
@end
@interface AI : Player <NPC>
@end
@implementation AI
@synthesize someNPCString;
- (void)foo
{
NSLog(@"foo");
}
- (void)bar
{
NSLog(@"bar");
}
@end
@interface viewController : UIViewController
@property (nonatomic) NSArray *humans;
@property (nonatomic) NSArray *npcs;
@end
@implmentation ViewController
-(void)viewDidLoad
{
id<Player> currentPlayer = nil;
humans = [NSArray arrayWithObject:[Player new]];
npcs = [NSArray arrayWithObjects:[AI new], [AI new], nil];
// message all player types, regardless of player or npc
for (Player *player in [humans arrayByAddingObjectsFromArray:npcs])
{
currentPlayer = player;
[player message];
if([player conformsToProtocl:@protocol(NPC)])
{
[(id<NPC>)player foo];
}
}
for (id<NPC>npc in npcs)
{
[npc bar];
npc.someNPCstring = @"str";
}
}
如您所見,這使您可以將npc像人類玩家一樣對待,如果需要,可以詢問玩家是否符合NPC協議,因此可以調用所需的協議方法,並根據它們的協議專門引用對象。
以我的拙見,當您開始需要將行為“混入”各種對象時,協議就變得最有意義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.