Inheritance Question

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

  1. russell.h macrumors regular

    Jul 2, 2007
    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:
    @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;
    But when I call the "count" method the console shows:
    *** -[NSArray count]: method only defined for abstract class.  Define -[LibraryItem count]!
    Am I doing something wrong? Thanks,

  2. HexMonkey Administrator


    Staff Member

    Feb 5, 2004
    New Zealand
    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. Eraserhead macrumors G4


    Nov 3, 2005
  4. russell.h thread starter macrumors regular

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

  5. iSee macrumors 68040


    Oct 25, 2004
    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. col. macrumors newbie

    Jun 24, 2008
    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?

  7. Catfish_Man macrumors 68030


    Sep 13, 2001
    Portland, OR
    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. adobongkangkong macrumors newbie

    Aug 26, 2008
    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){

    return (String)this.objectForKey("USERNAME");
    return new String();

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

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

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

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


    Jan 10, 2005
    Dallas, TX
    This was totally off-topic, but...

    "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:

  10. adobongkangkong macrumors newbie

    Aug 26, 2008
    Off topic Inheritance

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

Share This Page