Objective-c:为什么在使用KVC时私人ivars不会被外部访问隐藏

Cen*_*ion 7 encapsulation private objective-c setvalue ivars

在尝试使用KVC访问ivars之后,我注意到私人和受保护的ivars没有保护.我把它放在ivar(私人或受保护的关键字)前面并不重要 - 当使用KVC方法"setValue"时,ivar总是公共的ivar.这是我的代码,其中所有七个ivars和属性都可以在类实例之外更改:

//************ interface file ***************//
@interface MyClass : NSObject {
@public    
  NSNumber *public_num;
@protected 
  NSNumber *protected_num;
@private 
  NSNumber *private_num;
  NSNumber *private_property;
}
@property (retain) NSNumber *public_property;
@property (retain) NSNumber *private_property;
@end

//********* implementation file *********//
@interface MyClass(){
@private
  NSNumber *very_private_num;
}
@property (retain) NSNumber *very_private_property;
@end

@implementation MyClass
@synthesize public_property, private_property, very_private_property;
@end

//****** main **********//
MyClass *myClass = [[MyClass alloc] init];

[myClass setValue:[NSNumber numberWithInt:1] forKey:@"public_num"];
[myClass setValue:[NSNumber numberWithInt:2] forKey:@"protected_num"];
[myClass setValue:[NSNumber numberWithInt:3] forKey:@"private_num"];
[myClass setValue:[NSNumber numberWithInt:4] forKey:@"public_property"];
[myClass setValue:[NSNumber numberWithInt:5] forKey:@"private_property"];
[myClass setValue:[NSNumber numberWithInt:6] forKey:@"very_private_num"];
[myClass setValue:[NSNumber numberWithInt:7] forKey:@"very_private_property"];

NSNumber *l_public_num = [myClass valueForKey:@"public_num"];
NSNumber *l_protected_num = [myClass valueForKey:@"protected_num"];
NSNumber *l_private_num = [myClass valueForKey:@"private_num"];
NSNumber *l_public_property = [myClass valueForKey:@"public_property"];
NSNumber *l_private_property = [myClass valueForKey:@"private_property"];
NSNumber *l_very_private_num = [myClass valueForKey:@"very_private_num"];
NSNumber *l_very_private_property = [myClass valueForKey:@"very_private_property"];

NSLog(@"public_num = %@, protected_num = %@, private_num = %@, public_property = %@, private_property = %@, very_private_num = %@, very_private_property = %@", l_public_num, l_protected_num, l_private_num, l_public_property, l_private_property, l_very_private_num, l_very_private_property);
Run Code Online (Sandbox Code Playgroud)

输出的结果> public_num = 1,protected_num = 2,private_num = 3,public_property = 4,private_property = 5,very_private_num = 6,very_private_property = 7.

即使ivar在私人界面上声明,它仍然在课外变化.那么我如何必须强制执行封装和"保护我的ivars免受邪恶的其他程序员":)

Dan*_*rke 10

NSObject符合NSKeyValueCoding非正式协议.这定义setValue:forKey:valueForKey:.setValue:forKey:valueForKey:根据包括直接访问实例变量的特定搜索规则搜索访问密钥值的方法.这种直接访问由accessInstanceVariablesDirectly方法控制,该方法是NSKeyValueCoding非正式协议的一部分,该协议默认返回YES,允许这些方法直接访问实例变量,因此不会真正使它们成为私有.他们仍然是私人直接访问.

要解决此问题,您必须覆盖上述方法并在NSKeyValueCoding非正式协议中定义以防止其访问.

正如Abizern所提到的,私有变量的属性仍然可以访问,因为Objective-C没有私有方法的概念.

  • 我主要使用Obj-C和C++,并且在两种语言中都有办法绕过访问说明符,例如private和protected.实际上它只是使用该类的开发人员的指南或指示,他们不应该触摸任何未标记为公共的内容.虽然这个例子是一个库的解决方案,但也没有理由使用具有易于修改的头文件库的人不能完全从头文件中删除@private. (2认同)