Objective-C - частный против защищенного против публичного - PullRequest
37 голосов
/ 02 февраля 2011

Я надеюсь получить некоторые пояснения о том, как Private vs Protected vs Public работает в отношении участников класса при программировании в Objective-C - я думал, что знаю разницу (я добавил некоторые комментарии к своему родительскому классу 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;
        }

Разве компилятор не должен жаловаться, почему я пытаюсь получить доступ к aMan.yob выше?Или, используя @property & @synthesize (то есть методы setter и getter), я по существу сделал этот элемент защищенным и, следовательно, доступным для подкласса?

Ответы [ 4 ]

25 голосов
/ 02 февраля 2011

Обычный трюк - создать расширение класса внутри файла .m и поместить туда свое приватное / защищенное свойство вместо заголовка.

//Person.m

@interface Person()

@property float height

@end

это скрывает свойство 'height'

Другая хитрость в том, что если вы хотите создать свойство только для чтения, это объявить его в заголовке как

@property(readonly) int myproperty

, но в расширении класса как readwrite, что позволяет вашему .m изменять значение с помощью метода получения/ setter

@property(readwrite) int myproperty
17 голосов
/ 02 февраля 2011

видимость не влияет на методы. методы так же хороши, как публичные, когда они видны клиентам (и потенциальные ловушки / ошибки, когда они невидимы для клиентов). вместо этого видимость влияет на переменные экземпляра. попробуйте это:

#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.

3 голосов
/ 02 февраля 2011

Вы устанавливаете видимость иваров, а не свойства.Ваши свойства генерируют публичные методы получения и установки.

Чтобы сделать частные свойства, вы можете поместить свойства в частную категорию в файле .m.

2 голосов
/ 02 февраля 2011

Вы не обращаетесь к участникам - вы получаете доступ к свойству Person, для которого не указан уровень доступа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...