简体   繁体   English

Objective-C - 私人与受保护对公众

[英]Objective-C - Private vs Protected vs Public

I am hoping for some clarification on how Private vs Protected vs Public works with respect to class members when programming in Objective-C - I thought I knew the difference (I've added some comments to my parent class Person with respect to the same), but the fact that the compiler did not complain when I tried to access a private ivar/member of a parent class via the subclass now has me confused. 我希望在Objective-C中编程时,私有vs保护与公共关于类成员如何工作的一些澄清 - 我以为我知道区别(我已经向我的父类Person添加了一些注释)但是当我试图通过子类访问父类的私有ivar /成员时,编译器没有抱怨的事实让我感到困惑。

Here is my Parent Class: 这是我的父类:

/*
 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

Here is my derived class Man: 这是我的派生类Man:

    /*
     Man - Subclass of Person
    */

    #import <Foundation/Foundation.h>
    #import "Person.h"

    @interface Man : Person
    {
        //iVar for Man
        float mWeight;
    }
    @property float mWeight;

    @end

And finally, here is main: 最后,这里是主要的:

#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;
        }

Shouldn't the compiler complain why I try to access aMan.yob above? 难道编译器不应该抱怨为什么我尝试访问上面的man.yob? Or by using @property & @synthesize (ie the setter and getter methods) have I essentially made that member protected and therefore accessible to the subclass? 或者通过使用@property和@synthesize(即setter和getter方法),我基本上使该成员受到保护,因此可以访问子类?

The usual trick is to create a class extension inside the .m file and put your private/protected property there instead of in the header. 通常的技巧是在.m文件中创建一个类扩展,并将您的private / protected属性放在那里,而不是在标题中。

//Person.m

@interface Person()

@property float height

@end

this hides the 'height' property 这隐藏了'身高'属性

Another trick is if you want to create a readonly property is to declare it in the header as 另一个技巧是如果你想创建一个readonly属性是在头文件中声明它

@property(readonly) int myproperty

but in the class extension as readwrite which allows your .m to modify the value using the getter/setter 但在类扩展中作为readwrite,允许你的.m使用getter / setter修改值

@property(readwrite) int myproperty

visibility does not affect methods. 可见性不会影响方法。 methods are as good as public when visible to clients (and potential pitfalls/bugs when invisible to clients). 当客户可见时,方法与公众一样好(当客户看不到时,潜在的陷阱/错误)。 instead, visibility affects instance variables. 相反,可见性会影响实例变量。 try this: 试试这个:

#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;
        }

this prevents the subclasses from accessing ivars directly -- forcing them and clients to use the accessors (if provided). 这可以防止子类直接访问ivars - 强制它们和客户端使用访问器(如果提供)。

this is all a bit weak because categories allow clients to overcome this. 这有点弱,因为类别允许客户克服这一点。

also, older 32 bit objc programs did't really check that the visibility was declared correctly. 另外,较旧的32位objc程序并没有真正检查可见性是否被正确声明。 fortunately, that's been deprecated in 32 and an error in 64. 幸运的是,它在32中已被弃用,在64中有误。

if you really want something to be private to subclasses and categories, use PIMPL with an unpublished/opaque type. 如果你真的想要私有子类和类别,请使用未发布/不透明类型的PIMPL。

method visibility (as found in Java, C++, etc.) is a feature i'd use in objc. 方法可见性(如Java,C ++等中所见)是我在objc中使用的一个特性。

You are setting the visibilities of the ivars, not the properties. 您正在设置ivars的可见性,而不是属性。 Your properties generate public getter and setter methods. 您的属性生成公共getter和setter方法。

To make private properties, you can put the properties in a private category in the .m file. 要创建私有属性,可以将属性放在.m文件中的私有类别中。

您没有访问成员 - 您正在访问未指定访问级别的Person上的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM