Objective-C - 私有与受保护与公共

Posted

技术标签:

【中文标题】Objective-C - 私有与受保护与公共【英文标题】:Objective-C - Private vs Protected vs Public 【发布时间】:2011-06-19 16:31:16 【问题描述】:

我希望在使用 Objective-C 编程时,就类成员如何私有、受保护和公共如何工作 - 我想我知道其中的区别(我已经在我的父类 Person 中添加了一些 cmets相同),但是当我尝试通过子类访问父类的私有 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;
        

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

【问题讨论】:

旁注:如果你在 @ 实现块中编写你的 ivars,那么即使 @public 和 @protected 对子类也不可见。所以你的假设只对@interface 块是正确的。 【参考方案1】:

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

【讨论】:

protected 和 public 之间的可见性差异是什么。我认为 protected 应该只允许用于所有类的子类和公共。但是当我检查时,即使 protected 也没有造成任何错误其他类和 public.NOTE 相同的工作。注意-我在 .h 文件中添加了我的变量。【参考方案2】:

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

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

【讨论】:

最好使用类扩展而不是私有类别。【参考方案3】:

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

#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 中使用的一个特性。

【讨论】:

贾斯汀 - 感谢您的详细解释。现在说得通了! @noobzilla 没问题。快乐编码 @justin protected 和 public 之间的可见性区别是什么。我认为 protected 应该只允许用于所有类的子类和公共。但是当我检查时,即使 protected 也没有构成任何其他类中的错误并且与 public.NOTE 相同。注意-我已在 .h 文件中添加了我的变量。【参考方案4】:

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

//Person.m

@interface Person()

@property float height

@end

这隐藏了“高度”属性

另一个技巧是如果你想创建一个只读属性是在标题中声明它 作为

@property(readonly) int myproperty

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

@property(readwrite) int myproperty

【讨论】:

类扩展的好链接friday.com/bbum/2009/09/11/class-extensions-explained

以上是关于Objective-C - 私有与受保护与公共的主要内容,如果未能解决你的问题,请参考以下文章

ruby 公共与私人与受保护

公共与受保护

LayaBox---TypeScript---类

受保护的内部属性与受保护的属性和 Resharper

将 WordPress iOS 应用程序与受 Shibboleth 保护的 WordPress 配合使用

是否可以在 C++ 中将返回值移动语义与受保护的复制构造函数一起使用?