Re: Question
Re: Question
- Subject: Re: Question
- From: Greg Titus <email@hidden>
- Date: Mon, 3 Dec 2001 20:22:45 -0800
On Monday, December 3, 2001, at 06:37 PM, Eduardo I. Jiminez wrote:
>
Sure ObjC is great and it will tell me if I'm doing someting wrong in
>
runtime, but I really prefer C++'s way (that is, strong typing, where I
>
can specify what I want in) from a code clarity point of view. Also I
>
have some objects that could use operators, a great advantage of C++
>
(also for code clarity in structure navigation, object comparisons and
>
combining). Another reason NOT to use ObjC its because it is not
>
portable. I will not be able to use that code in the future to port the
>
application to another system, like Solaris, Linux, Windows or
>
whatever. But if my basic framework is in C++, I can use it anywhere.
So if you think C++ is the right language for your project and your
design, more power to you. Why not use it then? It seems fairly obvious
that that is your preference...
I wrote:
>
> If you are willing to go into some more detail about what your class
>
> design is trying to accomplish we (I) could probably be more helpful.
On Monday, December 3, 2001, at 06:37 PM, Eduardo I. Jiminez wrote:
>
Now, back to the point. Sure, I could fix the problem by coding a
>
composite object (can't use protocols because protocols cannot inherit
>
from classes, right?) with an union of both superclasses' interfaces,
>
forwarding calls to a couple of objects that represent each state of
>
the multiple superclass object, right?. However, this way I would not
>
gain type equivalence, having to use "id" as parameter type whenever I
>
need to receive an object like this one.
What I am about to say may still not be the best solution, which
frustrates me, but you still haven't given us enough information about
your design for me to really give decent advice. How many methods in
each superclass's interface? Do they have any methods in common? Do they
have a common ancestor? How many subclasses of each superclass? Is there
only a single class that you want to MI from the two, or is there a
hierarchy? Are the superclasses abstract or concrete classes? Are there
other concrete subclasses of each of the two superclasses?
Now, with that caveat, here's one approach:
- Define a protocol for each of your two interfaces.
- Declare each of your superclasses to implement the corresponding
protocol.
- Implement your 'MI' class as a composite: Subclass from NSObject or
other generic superclass, declare that this class implements both
protocols, and have it hold an instance of each of the two other classes
which it forwards methods to.
- Declare any parameters as objects that implement the required protocol
instead of being of a particular class.
For instance:
@protocol A
- methodA1;
- methodA2;
@end
@interface A : NSObject <A>
{
}
@end
@protocol B
- methodB1;
- methodB2;
@end
@interface B : NSObject <B>
{
}
@end
@interface MyMix : NSObject <A,B>
{
A *a;
B *b;
}
@end
Then pass these objects with the parameters typed as (id <A>) or (id
<B>).
Other things:
- If either the A protocol or the B protocol doesn't depend on instance
variables (not uncommon), consider not having a separate class to
implement it at all, but implement the methods as a category on NSObject:
@interface NSObject (CategoryAImplementation) <A>
@end
This does away with the need for an A object in the composite. (And
possibly the need for a composite at all.)
- If the A and B protocols have methods in common, the composite
approach has the advantage of being able to explicitly specify which of
the two (or both, or neither) of the implementations is actually called.
This is a common source of error in C++ MI.
- Consider the possibility of dynamically mixing in multiple behaviors
at runtime. The MyMix class could hold an array of objects that it is
the composite of, checking each in turn to find the first one which
implements a method.
- If A and B have a common superclass that contains most or all of the
meaningful state, consider making that superclass (C) use a delegate
pattern and refactor A and B as delegates of C instead of subclasses.
Then your MI situation becomes a chain-of-delegates pattern instead.
(Although you did say you avoid diamond shaped inheritance...)
Hopefully this gives you some ideas. There are a lot more potential
possibilities that depend on the details of what your design looks like
and how it will be used.
--Greg
References: | |
| >Re: Question (From: "Eduardo I. Jiménez" <email@hidden>) |