Access member data without a method - Objective-C

Discussion in 'Mac Programming' started by hiddenpremise, Jan 15, 2009.

  1. hiddenpremise macrumors regular

    hiddenpremise

    Joined:
    Jul 25, 2008
    Location:
    Somewhere between my imagination and reality
    #1
    Suppose I have a class defined in objective C with some variables within it
    Code:
    @interface myObject : NSObject
    {
    [INDENT]int variable1;[/INDENT]
    [INDENT]int variable2;[/INDENT]
    }
    @end //myObject
    
    I know that in C++ when I define a class, if those variables were "public" I could access them like "myObject.variable1" but that doesn't seem to work with objective-c. For the time being I have just written methods that will return those variables, but is there a way that I can access them without writing a method for each d**n variable?
     
  2. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #2
    Nope. You need accessors and mutators. They can be synthesized for you in Objective-C 2.0. See here:
    http://developer.apple.com/document.../ObjectiveC/Articles/chapter_5_section_3.html

    In my opinion, this is better. If you want something actually private, no accessor. If you want it readable, but not writable, no mutator. The only thing I miss is having something that's "shared" between objects of the same class, but not accessible otherwise.

    -Lee

    EDIT: Also, sadly (in my opinion), 2.0 introduced dot syntax for property access.
    http://developer.apple.com/DOCUMENT...html#//apple_ref/doc/uid/TP30001163-CH11-SW17
    Disgusting and confusing, in my opinion, but there it is. A dot on a pointer. Crazy.

    Edit 2: I am apparently totally wrong and misinformed. See bravobug's post below. I hope the @public stuff is new in 2.0.
     
  3. BravoBug macrumors newbie

    Joined:
    Dec 8, 2008
    Location:
    Oregon, USA
    #3
    This is possible in Objective C. You declare @public before the instance variables you would like to be public. They can then be accessed like members of a struct, such as:

    Code:
    myObject->variable1
    I can't find the link to the apple docs on this topic but they're in there somewhere, do a search and you can read more about this.

    EDIT: aha, here you go. Scroll down to read about @public. http://developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/chapter_3_section_4.html
     
  4. GorillaPaws macrumors 6502a

    GorillaPaws

    Joined:
    Oct 26, 2003
    Location:
    Richmond, VA
    #4
    While this is possible in Objective-C, it really goes against the way you're supposed to do things as far as my understanding goes. Stick to accessor methods as lee1210 described unless you have a good reason not to.
     
  5. MacDonaldsd macrumors 65816

    MacDonaldsd

    Joined:
    Sep 8, 2005
    Location:
    London , UK
    #5
    Agreed
     
  6. syberglitch macrumors newbie

    Joined:
    Feb 3, 2010
    Location:
    Manchester, UK
    #6
    Hi,

    First to point to a few things about this issue. It is not true that we cannot do that in Objective C as we can and it is perfectly legal. But is it safe that is another point.

    One example from Mac OSX Reference Library:
    http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-SW1

    Code:
    @interface Sibling : NSObject
    {
        Sibling *twin;
        int gender;
        struct features *appearance;
    }
    As long as the instance variables of the statically typed object are within the scope of the class (as they are here because twin is typed to the same class), a Sibling method can set them directly.

    Code:
    - makeIdenticalTwin
    {
        if ( !twin ) {
            twin = [[Sibling alloc] init];
            twin->gender = gender;
            twin->appearance = appearance;
        }
        return twin;
    }
    At the other extreme, marking a variable @public makes it generally available, even outside of class definitions that inherit or declare the variable. Normally, to get information stored in an instance variable, other objects must send a message requesting it. However, a public instance variable can be accessed anywhere as if it were a field in a C structure. For example:
    Code:
    Worker *ceo = [[Worker alloc] init];
    ceo->boss = nil;
    The whole point her is is it a good design or not as tampering with variable directly in most cases is not a good idea only because we can accidentally do something we do not want or even worse debugging and looking for the problem where problem is related with wrong usage of the variable is hard to find in this case. Using getters / setters is better as it is easier to debug and it is from design point of view a better practice as we have a code for dealing with the variable at one place . for instance we can do a boundary check in setter and in getter to inspect the value of the variable before we return its actual value.

    I forgot to mention one thing. To do this kind of construction the object must be statically typed.

    Conclusion:
    Marking instance variables @public defeats the ability of an object to hide its data. It runs counter to a fundamental principle of object-oriented programming—the encapsulation of data within objects where it’s protected from view and inadvertent error. Public instance variables should therefore be avoided except in extraordinary cases. Much better practice is to use @protected or @package depends on implementation.
     
  7. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #7
    If you feel the need to access every d**n member of an object, maybe it shouldn't be an object in the first place but just a plain C struct? I mean just because it's Cocoa and Objective-C doesn't mean everything has to be an object, if that is not appropriate.

    But _when_ you are using objects, whether in C++ or Objective-C, the members should just be an implementation detail that nobody except the implementation of your class should care about. When you start subclassing objects, reading a member directly is dangerous, and writing to one directly is most definitely asking for trouble. And at some point you will start using protocols, and then you don't even know what class an object belongs to.
     
  8. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #8
    But sometimes all you want is a struct-like object, which you can then insert into NSArrays (and apply predicates and stuff to), or add to NSDictionary, or serialize with NSCoding.

    Of course, it all depends on what you're trying to do, and the expected lifetime of the code. Sometimes it's just a throwaway or single purpose, and worrying about subclassing and all that crud isn't worth it.
     
  9. syberglitch macrumors newbie

    Joined:
    Feb 3, 2010
    Location:
    Manchester, UK
    #9
    I do not agre with the part that nobody except implementation of the class should care about. This is to hard definition as it constrains with subclassing, inheritance and many more design techniques.
    It is not true that using member variables is a bad thing in subclasses and members of an inheritance chain of a base class. That is perfectly legal and normal thing to do. I do not mean by this we should export our member variables trough the protected interface only. Just those we want to offer to the subclasses and there are many occasions we want to do that (Who says base classes, abstract classes, ...) On the other hand exporting member variables directly trough the public interface is from many point of views bad design as it can lead to many bad things in the code. Therefore using dedicated getters / setters is better and only because we know that there is only one place where we change the value of one variable. If we expose member variable trough the public interface and use it in a wrong way we can do the same think with getters and setters. But if we do wrong think with getter and setter IT IS WAY EASIER TO FIND IT AND DEBUG IT and there is less chance we will make a defect with using getters and setters then exposing variable to external class which is allowed to change its value. The whole point of exposing things to external classes (sources) is if we do not want to pass an ownership of an object or variable to external source then we should not expose the variable directly to the external sources at all times. Either as publicly available variable or returning the pointer to external source.
    In my previous post I have explained why it is dangerous to temper with public interface member variables of the class directly. It is the same think if we do it directly or trough the basic getter and setter. The only difference is that it is safer trough the getter and setter as we do it on one place and in those functions we can do a lot of checks before return or set the value or making is trade safe ... and all of that in one place.

    What we are talking about here is good and bad design and ood and bad programming practice.
    As I sad in my previous post:
    Marking instance variables @public defeats the ability of an object to hide its data. It runs counter to a fundamental principle of object-oriented programming—the encapsulation of data within objects where it’s protected from view and inadvertent error. Public instance variables should therefore be avoided except in extraordinary cases. Much better practice is to use @protected or @package depends on implementation.
     
  10. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #10
    @property and @synthesize, with or without the dot syntax, is probably your best shortcut, other than creating a struct. If you have a lot of variables to deal with, you might consider breaking them into objects themselves, sometimes that is the better plan.

    You really should stick to the object model defined by Objective-C and not deviate, like I have, into violations of the concept (I have a habit of creating "synthetic hybrid data structures" which connect data objects through internal links and use self as a frame pointer to navigate the structure).
     

Share This Page