繁体   English   中英

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

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

我希望在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

这是我的派生类Man:

    /*
     Man - Subclass of Person
    */

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

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

    @end

最后,这里是主要的:

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

难道编译器不应该抱怨为什么我尝试访问上面的man.yob? 或者通过使用@property和@synthesize(即setter和getter方法),我基本上使该成员受到保护,因此可以访问子类?

通常的技巧是在.m文件中创建一个类扩展,并将您的private / protected属性放在那里,而不是在标题中。

//Person.m

@interface Person()

@property float height

@end

这隐藏了'身高'属性

另一个技巧是如果你想创建一个readonly属性是在头文件中声明它

@property(readonly) int myproperty

但在类扩展中作为readwrite,允许你的.m使用getter / setter修改值

@property(readwrite) int myproperty

可见性不会影响方法。 当客户可见时,方法与公众一样好(当客户看不到时,潜在的陷阱/错误)。 相反,可见性会影响实例变量。 试试这个:

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

这可以防止子类直接访问ivars - 强制它们和客户端使用访问器(如果提供)。

这有点弱,因为类别允许客户克服这一点。

另外,较旧的32位objc程序并没有真正检查可见性是否被正确声明。 幸运的是,它在32中已被弃用,在64中有误。

如果你真的想要私有子类和类别,请使用未发布/不透明类型的PIMPL。

方法可见性(如Java,C ++等中所见)是我在objc中使用的一个特性。

您正在设置ivars的可见性,而不是属性。 您的属性生成公共getter和setter方法。

要创建私有属性,可以将属性放在.m文件中的私有类别中。

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

暂无
暂无

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

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