如何通过ios中的继承访问私有声明的属性

时间:2014-04-15 20:14:51

标签: ios objective-c

我不明白为什么我无法访问子类SetCardCardgameViewController中的self.cardButtons。父是CardgameViewController。

CardgameViewController.h:

 #import <UIKit/UIKit.h>
#import "Deck.h"

@interface CardgameViewController : UIViewController
- (void) updateUI;

//  protected
//  for subclasses

- (Deck *)createDeck;

// must be overriden in SetCardGameViewController as contents is not to be used for    instance
- (NSAttributedString *)titleForCard: (Card *)card;
- (UIImage *)backgroundImageforCard: (Card *)card;

@end

CardgameViewController.m

#import "CardgameViewController.h"
//#import "PlayingCardDeck.h"
#import "CardMatchingGame.h"

@interface CardgameViewController ()

@property (strong, nonatomic) CardMatchingGame *game;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
@property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
@property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UISlider *historySlider;
@property (weak, nonatomic) IBOutlet UILabel *historyOverview;

@end

SetCardCardgameViewController.h

#import "CardgameViewController.h"

@interface SetCardCardgameViewController : CardgameViewController

@end

SetCardCardgameViewController.m

#import "SetCardCardgameViewController.h"
#import "SetCardDeck.h"
#import "SetCard.h"

@interface SetCardCardgameViewController ()

@end

@implementation SetCardCardgameViewController

- (void)updateUI
{
    for (UIButton *cardButton in self.cardButtons) {

}

}

这最后一个self.cardButtons没有得到认可。但cardButtons是父类的属性。为什么它不被认可?我同意它是私下声明的,但由于SetCardCardgameViewController是CardgameViewController的孩子,我想我可以访问它的所有属性和方法。或者我错了?

2 个答案:

答案 0 :(得分:1)

你错误地将私有范围视为受保护的。

从语义上讲,由于Objective-C的动态特性,没有私有或受保护的范围。你可以像上面那样模仿私人范围;但是,.m文件中声明的方法或属性不能被其子类看到。将它们放在头文件中会使它们公开,并且通常是最常用的路径。如果绝对必须保护这些方法/属性,可以将该接口添加到单独的头文件中,然后将其导入子类中,如下所示:

CardgameViewController_Internal.h

@interface CardgameViewController (Private)

@property (strong, nonatomic) CardMatchingGame *game;
@property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
@property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
@property (weak, nonatomic) IBOutlet UISegmentedControl *matchMode;
@property (weak, nonatomic) IBOutlet UILabel *status;
@property (weak, nonatomic) IBOutlet UISlider *historySlider;
@property (weak, nonatomic) IBOutlet UILabel *historyOverview;

@end

然后在SetCardCardgameViewController.m中:

#import "SetCardCardgameViewController.h"
#import "SetCardDeck.h"
#import "SetCard.h"
#import "CardgameViewController_Internal.h"

@implementation SetCardCardgameViewController

- (void)updateUI
{
    for (UIButton *cardButton in self.cardButtons) { 

    }
}

@end

答案 1 :(得分:1)

您无法直接访问未在头文件中声明的任何属性,因为您没有从.m文件中导入任何符号,因此编译器不知道它们是否存在。

但是您的子类中的属性仍然存在,所以类似这样:

for (UIButton *cardButton in (NSArray*)[self valueForKey:@"cardButtons"])

工作,而不必在头文件中公开该属性。

如果您需要强类型属性(如您所愿),可以将类别(@interface CardgameViewController ())移动到私有变量的单独标题(类似CardgameViewController+Private.h),而不是将其声明为.m文件。然后,您将在基类和子类中导入此私有标头。