OC的私有、保护、公有和KVC

正确理解私有、保护和公有

在OC中属性默认都是公有的。如果有私有、保护和公有成员的需求,也可以通过OC关键字进行设置。

The Scope of Instance Variables

To enforce the ability of an object to hide its data, the compiler limits the scope of instance variables—that is, limits their visibility within the program. 
But to provide flexibility, it also lets you explicitly set the scope at four levels. Each level is marked by a compiler directive:

DirectiveMeaning
@privateThe instance variable is accessible only within the class that declares it.
@protectedThe instance variable is accessible within the class that declares it and within classes that inherit it. All instance variables without an explicit scope directive have @protected scope.
@publicThe instance variable is accessible everywhere.
@packageUsing the modern runtime, an @package instance variable has @public scope inside the executable image that implements the class, but acts like @private outside.The @package scope for Objective-C instance variables is analogous to private_extern for C variables and functions. Any code outside the class implementation’s image that tries to use the instance variable gets a link error.This scope is most useful for instance variables in framework classes,where @private may be too restrictive but @protected or @public too permissive.

通过上面文档,可以总结出在实例变量被直接操作的情况下,有以下可见性指令:
- @public:实例变量可使用符号 person->age = 32”被直接读取。
- @package:实例变量是公开的,除非它被指定在框架外(仅适用64位架构)
- @protected:实例变量仅可由其类和其衍生类访问
- @private:实例变量仅可由其类访问

对于@package,在stackoverflow上有一个很好的解释:
  • @package is similar to internal for .NET. It means the member is accessible only from the framework in which it is defined.
  • Note: In 32-bit it acts like @public.
    package 解释
OC中定义私有变量的方法
  1. 在.h中定义私有变量:

    @interface Father : NSObject {
          @private
          NSInteger  privateVar;
    }
    @end
  2. 通过Extension来定义私有变量

    @interface Father ()
    
    @property (nonatomic, strong) NSString  *song;
    
    @end
  3. 在implement中定义 私有变量

    @implementation Father {
          NSInteger   fAbc;
          NSString    *abcString;
    }
    @end
private、protected、public对比
@interface Father : NSObject {
    @private
    NSInteger  privateVar;
    
    @protected
    NSInteger   protectedVar;
    
    @public
    NSInteger   publicVar;
}
@end

在定义这些变量的类中可以访问私有的、保护的和公有的变量。而在它的子类中是不能访问私有变量的,只能访问保护的和公有的变量。
Screen Shot 2016-08-03 at 21.55.06.png
并且在实例化的对象中,只能访问公有变量,私有的和保护的变量均不能访问。
Screen Shot 2016-08-03 at 21.59.19.png

KVC方式访问变量

在父类中定义公有方法:

- (void)printPrivateVar
{
    NSLog(@"privateVar:%ld", privateVar);
    NSLog(@"protectedVar:%ld",protectedVar);
}

实例化对象通过KVC方式访问变量:

Father *father = [Father new];
[father setValue:@"123" forKey:@"privateVar"];
[father setValue:@"123456" forKey:@"protectedVar"];
[father printPrivateVar];
NSLog(@"father privateVar:%@", [father valueForKey:@"privateVar"]);
NSLog(@"father protectedVar:%@\n\n", [father valueForKey:@"protectedVar"]);

![Screen Shot 2016-08-03 at 22.22.57.png](http://upload-images.jianshu.io/upload_images/1171890-40e16cf17d85d768.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

Son *son = [Son new];
[son setValue:@"456789" forKey:@"privateVar"];
[son setValue:@"123456789" forKey:@"protectedVar"];
[son printPrivateVar];
NSLog(@"son privateVar:%@", [son valueForKey:@"privateVar"]);
NSLog(@"son protectedVar:%@", [son valueForKey:@"protectedVar"]);

打印结果如下:
Screen Shot 2016-08-03 at 22.22.57.png

extension和implement中定义的私有
Father类
//.h
@interface Father : NSObject {
    @private
    NSInteger   abc;
}

@property (nonatomic, strong) NSString  *songOne;

- (void)printVar;

@end

//.m
@interface Father () {
    @private
    int privateVar;
    @protected
    int protectedVar;
    @public
    int publicVar;
}

@property (nonatomic, strong) NSString  *song;

@end

@implementation Father {
    NSInteger   fAbc;
}

- (void)printVar
{
    NSLog(@"father abc:%@", [self valueForKey:@"abc"]);
    NSLog(@"father song:%@", [self valueForKey:@"song"]);
    NSLog(@"father songOne:%@", [self valueForKey:@"songOne"]);
    
    NSLog(@"father privateVar:%@", [self valueForKey:@"privateVar"]);
    NSLog(@"father protectedVar:%@", [self valueForKey:@"protectedVar"]);
    NSLog(@"father publicVar:%@\n\n", [self valueForKey:@"publicVar"]);
    
    NSLog(@"father fABC:%@", [self valueForKey:@"fAbc"]);
}

@end
son类
//.h
@interface Son : Father

- (void)printPrivate;

@end

//.m
@implementation Son

- (instancetype)init
{
    if (self = [super init]) {
    }
    return self;
}

- (void)printPrivate
{
    NSLog(@"son abc:%@", [self valueForKey:@"abc"]);
    NSLog(@"son song:%@", [self valueForKey:@"song"]);
    NSLog(@"son songOne:%@", [self valueForKey:@"songOne"]);
    
    NSLog(@"son privateVar:%@", [self valueForKey:@"privateVar"]);
    NSLog(@"son protectedVar:%@", [self valueForKey:@"protectedVar"]);
    NSLog(@"son publicVar:%@", [self valueForKey:@"publicVar"]);
    
    NSLog(@"son fABC:%@", [self valueForKey:@"fAbc"]);
}
@end

在实例化对象中通过KVC访问:

Father *father = [[Father alloc] init];
[father setValue:@"120" forKey:@"abc"];
[father setValue:@"123" forKey:@"songOne"];
[father setValue:@"456" forKey:@"song"];

[father setValue:@"12" forKey:@"privateVar"];
[father setValue:@"34" forKey:@"protectedVar"];
[father setValue:@"56" forKey:@"publicVar"];

[father setValue:@123456 forKey:@"fAbc"];

[father printVar];

Son *son = [Son new];
[son setValue:@"121" forKey:@"abc"];
[son setValue:@"1234" forKey:@"songOne"];
[son setValue:@"567" forKey:@"song"];

[son setValue:@"123" forKey:@"privateVar"];
[son setValue:@"456" forKey:@"protectedVar"];
[son setValue:@"789" forKey:@"publicVar"];

[son setValue:@1234567 forKey:@"fAbc"];

[son printPrivate];

打印结果
Screen Shot 2016-08-04 at 11.31.30 AM.png

通过KVC的方式不管是私有的、保护的和公有的,都能进行访问。

得到当前类运行时的变量列表
unsigned int count = 0;
Ivar *members = class_copyIvarList([Father class], &count);
for (int i = 0 ; i < count; i++) {
    Ivar var = members[i];
    const char *memberName = ivar_getName(var);
    const char *memberType = ivar_getTypeEncoding(var);
    NSLog(@"%s----%s", memberName, memberType);
}

打印Father类中变量为:
Screen Shot 2016-08-04 at 11.39.29 AM.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值