我希望在Objective-C中编程时,私有vs保护与公共关于类成员如何工作的一些澄清 - 我以为我知道区别(我已经向我的父类Person添加了一些评论)但是当我试图通过子类访问父类的私有ivar /成员时,编译器没有抱怨的事实让我感到困惑.
这是我的父类:
/*
Person.h
*/
#import <Foundation/Foundation.h>
@interface Person : NSObject
{
//We can also define class members/iVars that are of type private
//This means they can only be accessed by the member functions
//of the class defining them and not subclasses
@private
int yob;
//We can also define class members/iVars that are of type public
//Public members can be accessed directly
@public
bool alive;
//By default class members/iVars are of type protected
//This means they can only be accessed by a class's own
//member functions and subclasses of the class and typically
//also by friend functions of the class and the subclass
//We can explicitly define members to be protected using the
//@protected keyword
@protected
int age;
float height;
}
@property int age;
@property float height;
@property int yob;
@property bool alive;
@end
Run Code Online (Sandbox Code Playgroud)
这是我的派生类Man:
/*
Man - Subclass of Person
*/
#import <Foundation/Foundation.h>
#import "Person.h"
@interface Man : Person
{
//iVar for Man
float mWeight;
}
@property float mWeight;
@end
Run Code Online (Sandbox Code Playgroud)
最后,这里是主要的:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Create a Person object
Person * aPerson = [[Person alloc]init];
//Create a Man object
Man * aMan = [[Man alloc]init];
//Let's attempt to modify our Person class members
aPerson.height = 5.11; //Protected
aPerson.age = 21; //Protected
aPerson.yob = 2010; //Private
aPerson.alive = YES; //Public
//Let's now attempt to modify the same members via our
//derived class Man - in theory, the private members should
//not be accessible by the derived class man
aMan.height = 6; //Protected
aMan.age = 26; //Protected
aMan.yob = 2011; //Private
aMan.alive = YES; //Public
aMan.mWeight = 190; //Protected member of Man Class
[pool drain];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
难道编译器不应该抱怨为什么我尝试访问上面的man.yob?或者通过使用@property和@synthesize(即setter和getter方法),我基本上使该成员受到保护,因此可以访问子类?
And*_*rsK 26
通常的技巧是在.m文件中创建一个类扩展,并将您的private/protected属性放在那里,而不是在标题中.
//Person.m
@interface Person()
@property float height
@end
Run Code Online (Sandbox Code Playgroud)
这隐藏了'身高'属性
另一个技巧是如果你想创建一个readonly属性是在头文件中声明它
@property(readonly) int myproperty
Run Code Online (Sandbox Code Playgroud)
但在类扩展中作为readwrite,允许你的.m使用getter/setter修改值
@property(readwrite) int myproperty
Run Code Online (Sandbox Code Playgroud)
jus*_*tin 17
可见性不会影响方法.当客户可见时,方法与公众一样好(当客户看不到时,潜在的陷阱/错误).相反,可见性会影响实例变量.试试这个:
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Man.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//Create a Person object
Person * aPerson = [[Person alloc]init];
//Create a Man object
Man * aMan = [[Man alloc]init];
//Let's attempt to modify our Person class members
aPerson->height = 5.11; //Protected
aPerson->age = 21; //Protected
aPerson->yob = 2010; //Private
aPerson->alive = YES; //Public
//Let's now attempt to modify the same members via our
//derived class Man - in theory, the private members should
//not be accessible by the derived class man
aMan->height = 6; //Protected
aMan->age = 26; //Protected
aMan->yob = 2011; //Private
aMan->alive = YES; //Public
aMan->mWeight = 190; //Protected member of Man Class
[pool drain];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这可以防止子类直接访问ivars - 强制它们和客户端使用访问器(如果提供).
这有点弱,因为类别允许客户克服这一点.
另外,较旧的32位objc程序并没有真正检查可见性是否被正确声明.幸运的是,它在32中已被弃用,在64中有误.
如果你真的想要私有子类和类别,请使用未发布/不透明类型的PIMPL.
方法可见性(如Java,C++等中所见)是我在objc中使用的一个特性.
| 归档时间: |
|
| 查看次数: |
43699 次 |
| 最近记录: |