Inheritance Question

Discussion in 'Mac Programming' started by russell.h, Jan 16, 2008.

  1. macrumors regular

    Joined:
    Jul 2, 2007
    #1
    So I have this Class called "LibraryItem". It basically needs to store a mutable array along with a few strings.

    So I declared it like so:
    Code:
    @interface LibraryItem : NSMutableArray {
    	NSString *itemType;
    	NSString *itemPath;
    }
    
    - (id)initWithType:(NSString *)itemTypeToSet Path:(NSString *)path;
    - (void)setItemType:(NSString *)newType;
    - (void)setItemPath:(NSString *)newPath;
    - (NSString *)getItemType;
    - (NSString *)getItemPath;
    
    @end
    But when I call the "count" method the console shows:
    Code:
    *** -[NSArray count]: method only defined for abstract class.  Define -[LibraryItem count]!
    
    Am I doing something wrong? Thanks,

    Russell
     
  2. Administrator

    HexMonkey

    Staff Member

    Joined:
    Feb 5, 2004
    Location:
    New Zealand
    #2
    NSArray and NSMutableArray are part of a class cluster so can't easily be subclassed. From the NSArray documentation:

    More information on class clusters is available here.

    From a design perspective, however, your class should contain an array, not inherit it. What you are doing is known as inheritance for implementation, which means that you're inheriting a class for implementation purposes, not because it makes logical sense. By inheriting NSMutableArray, you're basically stating that LibraryItem is an array (which logically it isn't), and you're making it significantly more difficult to change your code in the future should you decide to change the way you store the list (for example, if you were to change it to use an NSMutableSet instead then you'd have to change every class that uses LibraryItem, rather than just the LibraryItem class).

    Another problem is that other classes could use LibraryItem in unexpected ways by using methods in NSMutableArray that you don't anticipate - an example of this problem is the Java API where Stack inherits Vector; this lets you, for example, remove an item from midway through the stack, which violates the rules of a stack.
     
  3. macrumors G4

    Eraserhead

    Joined:
    Nov 3, 2005
    Location:
    UK
    #3
    CoreData could be another alternative.
     
  4. thread starter macrumors regular

    Joined:
    Jul 2, 2007
    #4
    Good point, that fixes it and makes more sense too. Thanks,

    Russell
     
  5. macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #5
    A general rule of thumb when deciding between inheritence and containment to represent the relationship between two objects is this:

    Inheritence = is a
    Containment (member) = has a

    So, you just say/write/think the relationship and pick the one that makes sense:

    1. LibraryItem is an array
    2. LibraryItem has an array

    So in this case, #2 is the obvious choice.

    Actually, in the case of inheritance, it's better to say the relationship in a stronger way:

    Every <class 1> is a <class 2>.

    This will help you catch certain object model errors. (If the statement isn't true, you shouldn't try to represent the relationship as class 1 inherits from class 2.)
     
  6. macrumors newbie

    Joined:
    Jun 24, 2008
    #6
    But I really like sub-classing NSMutableDictionary :(

    I've just come across the same problem. It had me very confused but I found this thread and it explained the situation very well so thank you.

    However, I'm not so sure what I'm trying to do is a bad thing and I'd like to know if there IS a way for me to extend an NSMutableDictionary.

    I'm a Java WebObjects programmer that has been subclassing NSMutableDictionary for years and have found it extremely useful. Basically I find it to be a great way to create an class and to store any instance variables I like by calling setObjectForKey. Doing this has a lot of advantages such as:
    - it automatically provides key value coding
    - it automatically provides serialization and de-serialization in multiple formats
    - I can dynamically add properties to the object whenever I want
    - etc. etc.

    I'm now starting to do more and more Objective-C programming and would like to continue to subclass NSMutableDictionary when appropriate.

    I'm not experienced in Objective-C yet to figure out a way around the problem mentioned above. Does anyone have any advice as too weather this can be done or not?? and if so how?

    thanks
     
  7. macrumors 68030

    Catfish_Man

    Joined:
    Sep 13, 2001
    Location:
    Portland, OR
    #7
    Basically what you'd need to do is figure out which methods on NSMutableDictionary are its "primitive" methods (check the header file), and which ones are implemented in categories. Then have your subclass provide its own implementations of all the primitive methods, and the ones from categories should just work.
     
  8. macrumors newbie

    Joined:
    Aug 26, 2008
    #8
    Subclassing NSMutableDictionary

    @ col.

    Hi col. this is a bit off topic but this question is for you. You said you're a WebObjects programmer and have been subclassing dictionary I just want to know how did you subclass NSMutableDictionary. I have been subclassing NSMutableDictionary but everytime I use WOXMLCoder to serialize a subclass of NSMutableDictioanry it all resulst to its immutable counter part which is NSDictionary.

    e.g.: I have a class MyDictionary that extends NSMutableDictionary.
    My MyDictionary has the following methods.

    setUserName(String username){
    this.setObjectForKey(username,"USERNAME");
    }

    userName(){
    if(this.containsKey("USERNAME")){
    return (String)this.objectForKey("USERNAME");
    }else{
    return new String();
    }
    }

    And when I serialized MyDictionary object using WOXMlCoder the result is this.

    <ROOT type="com.webobjects.foundation.NSDictionary" objectID="1">
    <USERNAME type="java.lang.String" objectID="2">myusername</USERNAME>
    </ROOT>

    Notice that the type of the ROOT document is "com.webobjects.foundation.NSDictionary" why not "MyDictionary" or "NSMutableDictionary" why "NSDictionary" ?

    Please reply to this post and thanks in advance.
     
  9. macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #9
    This was totally off-topic, but...
    http://developer.apple.com/document...bobjects/appserver/xml/WOXMLCoder.html#coder()

    "an instance of NSArray, NSDictionary and NSData. Please note that before WebObjects 5.1, when the mutable forms of these classes (NSMutableArray, NSMutableDictionary and NSMutableData) are encoded using WOXMLCoder, they get written out as their immutable counterparts. For example, NSMutableArray used to be written out as NSArray. Now, they get written out as themselves. As a result, when WOXMLDecoder is used to decode the objects, they are decoded as mutable forms."

    If you are using WebObjects less than 5.1, it looks like this is known behavior.

    If you can't get around this behavior, you should be able to get yourself an NSMutableDictionary from the decoded NSDictionary with:

    http://developer.apple.com/document...ionary(com.webobjects.foundation.NSDictionary)

    -Lee
     
  10. macrumors newbie

    Joined:
    Aug 26, 2008
    #10
    Off topic Inheritance

    BTW, I'm using WebObjects 5.3 as I don't have Leopard yet.
     
  11. macrumors regular

    Joined:
    Oct 14, 2005
    Location:
    Troy, NY

Share This Page