Multiple inheritance and objective-c

  • I an objective-c architecture question:

    I have class B that inherits from class A.  I now need to make a class
    C.  It turns out that 90% of  the functionality (including class
    variables) would be shared between B's implementation (its subclass
    implementation) and C's implementation.  In C++, I would break out that
    functionality, creating class D.  Class B would inherit from A AND D,
    while C would inherit from D.  I know that objective-c doesn't have
    multiple inheritance, so I was wondering how similar class
    functionality is handled there.  Note that I DO have class variables
    (instance variables), which precludes using categories to support this.

    Mark
  • On 21 Mar, 2005, at 6:11 PM, Mark Dawson wrote:
    >
    > I have class B that inherits from class A.  I now need to make a class
    > C.  It turns out that 90% of  the functionality (including class
    > variables) would be shared between B's implementation (its subclass
    > implementation) and C's implementation.  In C++, I would break out
    > that functionality, creating class D.  Class B would inherit from A
    > AND D, while C would inherit from D.  I know that objective-c doesn't
    > have multiple inheritance, so I was wondering how similar class
    > functionality is handled there.  Note that I DO have class variables
    > (instance variables), which precludes using categories to support
    > this.

    Can you just make Class C keep an instance of Class B as an instance
    variable?

    -John
  • That would improve the issue, but that would still mean that I'd have
    to implement all of the method, even if that just meant passing them
    through, right?  I have 20-30 methods that are in common.

    So class C would have
    @@interface class C {
      NSMutableArray * mArray;
    }
    -getXXX1;  ... -getXXX10;
          -setXXX1(int) x;  ... -setXXX10(int) x;
    @end

    Class B would look something like (assuming I could inline like C++):
    @interface class B : class A {
    C *mSharedClass;
    };
    -getXXx1() { return [mSharedClass getXXX1]; }
    ..
    -getXXx01() { return [mSharedClass getXXX10]; }
    @end
    On Mar 21, 2005, at 3:15 PM, John C. Warner wrote:

    >
    > On 21 Mar, 2005, at 6:11 PM, Mark Dawson wrote:
    >>
    >> I have class B that inherits from class A.  I now need to make a
    >> class C.  It turns out that 90% of  the functionality (including
    >> class variables) would be shared between B's implementation (its
    >> subclass implementation) and C's implementation.  In C++, I would
    >> break out that functionality, creating class D.  Class B would
    >> inherit from A AND D, while C would inherit from D.  I know that
    >> objective-c doesn't have multiple inheritance, so I was wondering how
    >> similar class functionality is handled there.  Note that I DO have
    >> class variables (instance variables), which precludes using
    >> categories to support this.
    >
    > Can you just make Class C keep an instance of Class B as an instance
    > variable?
    >
    > -John
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/
    > <macengineering...>
    >
    > This email sent to <macengineering...>
    >
  • On Mar 22, 2005, at 00:32, Mark Dawson wrote:

    > That would improve the issue, but that would still mean that I'd have
    > to implement all of the method, even if that just meant passing them
    > through, right?  I have 20-30 methods that are in common.

    You could transparently proxy them. Check -forwardInvocation.

    Cheers

    --
    PA, Onnay Equitursay
    http://alt.textdrive.com/
  • A big question here is how much flexibility you have.  If you can't
    change B because you don't own it, or others already use and depend on
    it, then your options are different than if you can change it.

    If you own B and can do what you want with it, and assuming that B and
    C have 10% different from each other.  Then a few of options I see are:

    - Add the 90% to A and subclass both B and C from A
    - Create a new subclass of A called D with the shared 90% and subclass
    B and C from it.
    - A non-obvious one to C++/Java programmers is simply add C's
    differences to B.  One of the things that Apple's frameworks due well
    is to not over fragment.  This isn't a call that can be made without
    knowing more, but it isn't necessarily wrong to have a large B rather
    than slightly smaller B and C separately (ex: NSWindow is *huge* and it
    is a good thing).  Generally Obj-C classes (by convention) tend to be
    larger than C++ or Java classes.

    If you don't own B then your options are more restricted, and can get
    uglier.

    - Subclass C from B ignoring what C doesn't use out of B
    - Slap a category on B (or even A) that forwards C's additional 10% to
    C
    - Use poseAsClass: to replace B with MyBC which has your additional
    instance variables
    - Use a class variable to sneak in some added instance variables

    There isn't a single answer, it very much depends on the situation.  If
    you have the option, code re-organization is usually the best.  C++
    class hierarchies do not usually look much like Obj-C ones for
    equivalent functionality.

    Hope this is at least a little help.

    -Mont

    On Mar 21, 2005, at 3:32 PM, Mark Dawson wrote:

    > That would improve the issue, but that would still mean that I'd have
    > to implement all of the method, even if that just meant passing them
    > through, right?  I have 20-30 methods that are in common.
    >
    > So class C would have
    > @@interface class C {
    > NSMutableArray * mArray;
    > }
    > -getXXX1;  ... -getXXX10;
    > -setXXX1(int) x;  ... -setXXX10(int) x;
    > @end
    >
    > Class B would look something like (assuming I could inline like C++):
    > @interface class B : class A {
    > C *mSharedClass;
    > };
    > -getXXx1() { return [mSharedClass getXXX1]; }
    > ..
    > -getXXx01() { return [mSharedClass getXXX10]; }
    > @end
    > On Mar 21, 2005, at 3:15 PM, John C. Warner wrote:
    >
    >>
    >> On 21 Mar, 2005, at 6:11 PM, Mark Dawson wrote:
    >>>
    >>> I have class B that inherits from class A.  I now need to make a
    >>> class C.  It turns out that 90% of  the functionality (including
    >>> class variables) would be shared between B's implementation (its
    >>> subclass implementation) and C's implementation.  In C++, I would
    >>> break out that functionality, creating class D.  Class B would
    >>> inherit from A AND D, while C would inherit from D.  I know that
    >>> objective-c doesn't have multiple inheritance, so I was wondering
    >>> how similar class functionality is handled there.  Note that I DO
    >>> have class variables (instance variables), which precludes using
    >>> categories to support this.
    >>
    >> Can you just make Class C keep an instance of Class B as an instance
    >> variable?
    >>
    >> -John
    >>
    >> _______________________________________________
    >> Do not post admin requests to the list. They will be ignored.
    >> Cocoa-dev mailing list      (<Cocoa-dev...>)
    >> Help/Unsubscribe/Update your Subscription:
    >> http://lists.apple.com/mailman/options/cocoa-dev/
    >> <macengineering...>
    >>
    >> This email sent to <macengineering...>
    >>
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/
    > <mont_rothstein...>
    >
    > This email sent to <mont_rothstein...>
  • On Mar 21, 2005, at 3:51 PM, Mont Rothstein wrote:

    > A big question here is how much flexibility you have.  If you can't
    > change B because you don't own it, or others already use and depend on
    > it, then your options are different than if you can change it.
    I own them, so I have the flexibility
    > If you own B and can do what you want with it, and assuming that B and
    > C have 10% different from each other.  Then a few of options I see
    > are:
    >
    > - Add the 90% to A and subclass both B and C from A
    Maybe I wasn't clear--class A's functionality has nothing to with C's.
    The shared functionality has to with what B is adding to A (via the
    subclass).
    - Create a new subclass of A called D with the shared 90% and subclass
    B and C from it.
    > - A non-obvious one to C++/Java programmers is simply add C's
    > differences to B.  One of the things that Apple's frameworks due well
    > is to not over fragment.  This isn't a call that can be made without
    > knowing more, but it isn't necessarily wrong to have a large B rather
    > than slightly smaller B and C separately (ex: NSWindow is *huge* and
    > it is a good thing).  Generally Obj-C classes (by convention) tend to
    > be larger than C++ or Java classes.
    I had thought about making C a subclass of B.  It would carry all of
    A's overhead, but that wouldn't harm anything functionality-wise.  I
    wasn't sure if that was good "OO" programing practice, though.
    >
    > Hope this is at least a little help.
    Thanks,

    Mark
  • If A has nothing to do with C, yet B (a subclass of A) shares 90% of
    its code with C... That sounds a bit crooked to me :)
    Can you have B and C both inherit from a shared class D, then have A be
    a subclass of B? Or simply have A and C inherit from D, and skip B
    altogether?

    On Mar 21, 2005, at 19:09, Mark Dawson wrote:

    > Maybe I wasn't clear--class A's functionality has nothing to with C's.
    > The shared functionality has to with what B is adding to A (via the
    > subclass).
  • On 22/03/2005, at 11:09, Mark Dawson wrote:

    >> If you own B and can do what you want with it, and assuming that B
    >> and C have 10% different from each other.  Then a few of options I
    >> see are:
    >>
    >> - Add the 90% to A and subclass both B and C from A
    > Maybe I wasn't clear--class A's functionality has nothing to with C's.
    > The shared functionality has to with what B is adding to A (via the
    > subclass).

    Maybe your class hierarchy is inverted, that is, maybe A should inherit
    from B rather than vice versa?  Then C could also inherit from B to
    pick up the functionality it needs.

    There is such an abstract description of the problem at hand, it's hard
    to know how to best solve it.  Perhaps the use of a delegate might help
    but I'm not sure.

    Ben.
  • >> If A has nothing to do with C, yet B (a subclass of A) shares 90% of
    >> its code with C... That sounds a bit crooked to me :)
    >> Can you have B and C both inherit from a shared class D, then have A
    >> be a subclass of B? Or simply have A and C inherit from D, and skip B
    >> altogether?
    >>
    > A is a class that is operated on by other classes.  B is a class that
    > groups classes of A (or B) together.  Code may say "if ( [object
    > hittest:point])".  If "object" is of class "B", it passes the hittest
    > message to each of the objects it is grouping, returning true if any
    > of its objects have been hit (class B won't always pass through
    > messages, but it sometimes does, as in the hittest case).  Class C
    > implements the same grouping methods as B, however it doesn't need to
    > be treated as a class of A, nor does it need to respond to most of the
    > methods of class A.
    >
    > I COULD make C a subclass of B, which would handle all of the shared
    > code issues.  It just would also include class A, which isn't
    > bad--just more overhead and not necessary (maybe that's not as bad of
    > a "word" in Objective-C as it is in C++?)
    >
    > Mark

    I don't think a "group of object" should be a subclass of "object".
    Grouping other objects is a concept in itself, and it belongs separate
    from the objects it groups (as your dilemma demonstrates). I'd suggest
    trying to create a "group of" base class, that would implement the
    grouping behavior, then subclassing that to create concrete group
    classes. In terms of your examples, I'd create a class G with the
    shared grouping behavior, then derive A and C from G. In fact, from
    your description, I gather that you want a "group of A" to behave
    pretty much like an A from the outside. So why not make the two the
    same? Make A an entity that can either stand alone, or else contain a
    list of A's, in which case it relays its messages to the grouped
    objects as you describe.
    Making C derive from B would be clunky, since what you want to inherit
    is the grouping functionality, not class A's behavior. Shared behavior
    belongs higher up in the inheritance chain, and specializations belong
    lower.

    Serge
  • A real multiple inheritance solution was described last September and
    discussed in a cocoa-dev thread titled "Multiple Inheritence (Was: Is
    _objc_flush_caches_(Class) necessary to swizzle methods?)":

    http://www.cocoabuilder.com/archive/message/2004/9/25/118263
    http://www.cocoabuilder.com/archive/message/cocoa/2004/9/26/118320

    You can achieve a kind of "weak" multiple inheritance in Obj-C by using
    the #include or #define directives of the C-preprocessor.  Omni does
    the later in their frameworks to effectively place all the code used in
    multiple, otherwise unrelated, classes in one place.  LIkewise, one can
    then implement what are effective "concrete" protocols this way as
    well.

    The technique is simple and work well in Xcode.  The only problem,
    which is minor, is that if you place a breakpoint in the shared code in
    registered for only one of the classes that use that code.

    So, here is what you do to use #include:

    1.)  Write you shared code out in file that is not added to your target
    so it is not complied, as will not compile independently.  The shared
    should be method implementations only, that is outside of the normal
    @implementation - @end blocks.

    2.) Use #include like so:

      @implementation MyClassWithWeakMultipleInheritence

      #include "myCommonMethodImpementations.m"

      - (void)myClassSpecificMethod
      {

      NSLog(@"This is myClassSpecificMethod of 
      MyClassWithWeakMultipleInheritence");

      }

      @end

    If you have only short amount of code that is common to multiple
    classes you can use a multiple line #define instead of an entire file.

    Hope this helps, I know it did for me.

    Gordon G.
previous month march 2005 next month
MTWTFSS
  1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31      
Go to today