• A basic question on private/public variables and data encapsulation

    From Jon Rossen@21:1/5 to All on Sat Jan 30 17:01:26 2016
    I'm a relatively new programmer, and not a single book that I'm using
    has given concrete examples or underlying reasons as to why 'protecting'
    your iVars by declaring them in @implementation rather than @interface
    might be important or ever be important. Since each instance has their
    own copy of the instance variables anyway, what is the potential for
    doing something destructive?

    Let's say you have a class called A which has a subclass B. In class A,
    you have an iVar declared in @implementation named int x. Therefore
    instances of class B (as a subclass of class A), do not have direct
    access to x. If int x was declared in class A's @interface section, the
    iVar int x would be public and could be directly accessed by class B
    instances just as it can be by class A instances. Here's an example of
    a method in class B, the subclass:
    // A method of class B (which is a subclass of A)
    -(void) printVar
    {
    NSLog(@"The value of x is %d", x);
    }

    In this example, you'd get an error if x was declared in class A's implementation section, but no error if 'x' was public by being declared
    in class A's interface section.

    THE CORE QUESTION:
    So, what is the reason for worrying about public vs private? There is
    data encapsulation *already established anyway* solely due to the fact
    that each instance has it's own set of instance variables. So, you have
    that protection. For example if an object from the subclass (in this
    example class B) had direct access to x, so what? It has its own x.
    Why would you ever be concerned over the amount of access subclasses
    would have to the parent class's instance variables? What would or
    could you gain by keeping the iVars private?

    Note: I should add that I'm already familiar with accessor methods and properties, etc. etc. and would hope that any answer didn't essentially
    be a treatise on that stuff. An answer to the core question is really
    what I'm curious about. Thanks for any info. (In other words I do
    already know that x could be accessed by class B using any accessor
    methods inherited from class A)

    Btw, I fully know that the silly, simple code example I provided is
    contrived and is sort of a 'strawman' argument so to speak. When you
    are using beginner's books they really don't give you any real world use
    cases as examples because the goal is to teach you basic structure and
    syntax. However, the code example was given to illustrate my question.



    -jonR

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Louis Wu@21:1/5 to Jon Rossen on Sat Jan 30 21:09:46 2016
    In article <n8jmdc$6go$1@news.albasani.net>,
    Jon Rossen <jonr17@comcast.net> wrote:

    I'm a relatively new programmer, and not a single book that I'm using
    has given concrete examples or underlying reasons as to why 'protecting'
    your iVars by declaring them in @implementation rather than @interface
    might be important or ever be important. Since each instance has their
    own copy of the instance variables anyway, what is the potential for
    doing something destructive?

    Well, they're mostly important if you're writing a class that you plan
    to make generic and reuse later (or, even better, make available to
    other people to use).

    I use them more for convenience than terror of destruction, same with
    messages defined in the implementation. Let me give you an example of
    where (and why) I've used both in the past.

    I have written a "generic" page writing routine which accepts an NSArray
    of printable objects, each object starts with a bounding NSRect, some
    text and formatting information which describes how the text should be
    drawn within the box. Each box may also contain another list of boxes
    contained in the bounding box

    So, I might write the class interface with

    (id) initBlockWithPageWidth:(float)width andHeight:(float)height;

    (NSErr*) writeBlocks:(NSArray*) toPDFFile:(NSURL*)pdfURL;

    and declaring 2 ivars, pageWidth and pageHeight. Anyone wishing to use
    this class knows immediately what they need to supply and os pretty sure
    about when to issue the messages and doesn't need to know anything more
    about the class.

    That is, the client really needs to tell me, how big is the page when
    they create the report, and then give me the list of blocks to print,
    and the URL of the PDF file to write it into. The class does everything
    else (on its own) and, if there's any kind of problem, it'll return an
    NSErr describing that problem.

    However, it's obvious that I'm going to need to share a lot of
    information inside the implementation about current locations, calculate NSAttributedTexts and do a lot of horizontal and vertical shuffling of
    the resultant mess inside its box and then inside the page, and I DON'T
    want to have to pass 10 or 15 variables as parameters through all those function calls. I also don't want to have all my intermediate x/y data
    and calculations to be declared in the interface so that any client
    using the class see them and be confused about when to call them and
    what data to supply - they're not intended for the client at all !

    You see, if I declare variables and methods in the implementation, I can
    make them instantly available to the entire class without having to
    introduce a whole bag of used kitty litter into the interface. It
    remains simple, clear and minimal so the client is only presented with
    things they need to call and data they need to provide.

    Did that help ?

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ben Bacarisse@21:1/5 to Jon Rossen on Sun Jan 31 15:37:51 2016
    Jon Rossen <jonr17@comcast.net> writes:

    I'm a relatively new programmer, and not a single book that I'm using
    has given concrete examples or underlying reasons as to why
    'protecting' your iVars by declaring them in @implementation rather
    than @interface might be important or ever be important. Since each
    instance has their own copy of the instance variables anyway, what is
    the potential for doing something destructive?

    Not knowing objective C, I will certainly get some of the words wrong,
    but let have have a go...

    Let's say you have a class called A which has a subclass B. In class
    A, you have an iVar declared in @implementation named int x.
    Therefore instances of class B (as a subclass of class A), do not
    have direct access to x. If int x was declared in class A's
    @interface section, the iVar int x would be public and could be
    directly accessed by class B instances just as it can be by class A instances. Here's an example of a method in class B, the subclass:
    // A method of class B (which is a subclass of A)
    -(void) printVar
    {
    NSLog(@"The value of x is %d", x);
    }

    In this example, you'd get an error if x was declared in class A's implementation section, but no error if 'x' was public by being
    declared in class A's interface section.

    THE CORE QUESTION:
    So, what is the reason for worrying about public vs private? There is
    data encapsulation *already established anyway* solely due to the fact
    that each instance has it's own set of instance variables. So, you
    have that protection. For example if an object from the subclass (in
    this example class B) had direct access to x, so what?

    Encapsulation is also about hiding representation's and preserving relationships between data in a way that can make debugging much
    simpler.

    Let's say you have class that represents a partitions of the set {1, 2,
    3, .. n}. You give it n has methods to move number into new
    subsets, or from one to the other.

    Let's also say that you just use bits set in a word to represent these
    sets. If a derived class can access these words you no longer have
    proper encapsulation. The derived class might (as a result of a bug or
    on purpose) set a bit in one word without unsetting it in the others. Or
    it might set a bit corresponding to n+1 making the object have an
    element it should never have. The methods of the base class might now
    break.

    And when find that the internal state of the object is inconsistent (say
    that is has 42 in two subsets) where do you look? If all the data is
    private the error must be in one of the methods. If the data is public,
    you have all sorts of places to look.

    Finally, you now find yourself stuck with that representation. If the
    data are private, you can change to using bit vectors or lists or hash
    tables knowing that the only code you'll need to change is in one
    place -- that class's methods. With a public representation you may not
    be able to change it at all since you may not be the author of all the
    derived classes.

    Does that help?

    <snip>
    --
    Ben.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From spikeysnack@21:1/5 to All on Sun Jan 31 14:18:39 2016
    Hi. Before I begin my rant, I would like to clarify some common misconceptions about information hiding.
    First, it is not actually hiding anything. It is a design concept in computer science that is about back-end/front-end and api presentation, and the idea that an object carries with it data and methods of manipulating its data along with it.
    Second, it has never been a security feature, it is an organization strategy. So throw out any ideas you may have picked up about safety of security of data based on @public @protected and @private in Objc. They aren't there.
    They are "hints" to the compiler at compile-time that accesses are occurring from outside the class but not errors.
    Any variable or method in the class implementation is available to be run or accessed directly during runtime. If it is not "advertised" in the .h file as part of the API then the idea is ordinary users of the class in programmming will avoid accessing
    it and probably will not know it is available. The protection aspect is the class designer just doesn't want people fooling around with some variable or using some method that should be internal to the class, but if you know about it you can access it,
    even if you get a warning from the compiler. Traditionally ObjC is very lax about letting programmers off with warnings.
    If you ship a set of libraries with .h files, compiled library files, and no .m files you can see that "unadvertised" methods not in the header files will probably not get used by consumers (programmers using your library to program with). If you ship
    full source, they can look at it and it is all open to them to use if they want.
    In some languages information hiding is enforced, and it is an error to access private variables by outside classes, but in ObjC it is just a warning. The warning is valid, however, in that you are probably doing it wrong if you have to run internal
    methods or bypass getter/setters to manipulate class data.
    @public
    @protected
    @private
    are hints for you the designer of the class to make your api appropriately for the consumer of the class.
    We want to avoid stuff like this:

    struct
    { int a; char* c; }
    x_struct;


    @interface class A
    {
    @private
    x_struct x;
    }

    then somewhere you write:
    x.a = 42; // direct access
    x.c = "a string";
    char* mystr = xs->x.c;

    This is all perfectly valid C and will compile and run and may even be what you want, but it is a dangerous operation and can have all kinds of unintended consequences especially becuase it circumvents any data cleaning or verification before setting values that may destroy the class or lead to creating garbage data or even crashes.
    When this look like the way to go you know you have gone off the rails and need to redesign your interfaces or go through the task of writing some coherent accessor/setter code.
    Objects produce, consume, and manipulate data and take up memory space to do so, so violating that memory space from without the class can cause damage to data and the system especially if pointers are involved.
    Direct assignment of pointers from outside of the class to inside of the class is the worst form of violation of information hiding and is a major reason
    object oriented programming exists. Don't do that.
    @interface class A
    {
    @public
    SomeClass * sc;
    }

    sc = [SomeClass new]; // OK inside internal A method , not anywhere else, though.
    Trouble is this seem reasonable when inside of A.h but carries no protection at runtime that the running program will assign A.sc a good SomeClass object.
    So a setter should be written for setting A.sc , preferrably one that validates it before assigning the pointer to the object.

    The rub comes when the API provided is complicated and feels cumbersome like the old Foundation Classes or the
    inputstream->input-filter->input->reader->input-validator->input->consumer>input-data
    data-processing ==>
    output-data>output->writer>output-filter>outputstream
    paradigm is used.
    Seems shockingly bulky and inefficient, and takes a lot of coding time and debugging. It seems so much easier to just set a variable or assign a pointer. It is, but it is also a good way to crash programs, and write unmaintainable, hard to modify code,
    and to leak data or expose it to modification by accident.

    Hey though, if you want transparency in your class you can do that.
    But You can not make a real private instance variable.
    it's always possible to access any variable (even @private ones). It may seem like it from the documentation but that is just assuming good practices on your part.
    The question then becomes: When should you violate information hiding?
    Ah. Well. You can have up to one lifetime to figure that one out.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)