Vraag Objectief-C - Privé versus beschermd versus publiek


Ik hoop op enige opheldering over hoe Private vs Protected vs Public met betrekking tot de cursisten werkt bij het programmeren in Objective-C - Ik dacht dat ik het verschil kende (ik heb wat opmerkingen aan mijn ouderklasse toegevoegd met betrekking tot hetzelfde) , maar het feit dat de compiler niet klaagde toen ik probeerde toegang te krijgen tot een privé-ivar / lid van een ouderklasse via de subklasse, heeft me nu in de war gebracht.

Hier is mijn bovenliggende klasse:

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

Hier is mijn afgeleide klasse Man:

    /*
     Man - Subclass of Person
    */

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

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

    @end

En tenslotte, hier is het belangrijkste:

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

Moet de compiler niet klagen waarom ik toegang probeer te krijgen tot eenMan.yob hierboven? Of heb ik met behulp van @property & @synthesize (dat wil zeggen de methoden setter en getter) dat lid in feite beschermd en daarom toegankelijk voor de subklasse?


34
2018-02-02 01:34


oorsprong


antwoorden:


zichtbaarheid heeft geen invloed op methoden. methoden zijn zo goed als publiek wanneer ze zichtbaar zijn voor clients (en potentiële valkuilen / bugs wanneer ze onzichtbaar zijn voor clients). in plaats daarvan beïnvloedt zichtbaarheid instantievariabelen. probeer dit:

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

dit voorkomt dat de subklassen rechtstreeks toegang krijgen tot ivars - dwingt hen en clients om de accessors te gebruiken (indien aanwezig).

dit is allemaal een beetje zwak omdat de categorieën klanten in staat stellen dit te overwinnen.

oudere 32 bit objc-programma's hebben ook niet echt gecontroleerd of de zichtbaarheid correct is verklaard. gelukkig is dat gedeprecieerd in 32 en een fout in 64.

als je echt wilt dat iets privé is voor subklassen en categorieën, gebruik je PIMPL met een niet-gepubliceerd / ondoorzichtig type.

methode zichtbaarheid (zoals gevonden in Java, C ++, etc.) is een functie die ik zou gebruiken in objc.


17
2018-02-02 02:43



De gebruikelijke truc is om een ​​klasse-extensie in het .m-bestand te maken en je privé- / beschermde property daar te plaatsen in plaats van in de header.

//Person.m

@interface Person()

@property float height

@end

dit verbergt de eigenschap 'height'

Een andere truc is als u een readonly-eigenschap wilt maken, moet u deze in de koptekst declareren als

@property(readonly) int myproperty

maar in de klasse-extensie als readwrite waarmee uw .m de waarde met behulp van de getter / setter kan wijzigen

@property(readwrite) int myproperty

24
2018-02-02 02:48



U bepaalt de zichtbaarheid van de ivars, niet de eigenschappen. Uw eigenschappen genereren openbare methoden voor getter en setter.

Als u privé-eigenschappen wilt maken, kunt u de eigenschappen in een privécategorie in het M-bestand plaatsen.


3
2018-02-02 01:38



U hebt geen toegang tot de leden - u gebruikt de property op Person waarvoor het toegangsniveau niet is opgegeven.


2
2018-02-02 01:37