Re: Mutable and immutable class cluster implementation / "method swizzling" question
Re: Mutable and immutable class cluster implementation / "method swizzling" question
- Subject: Re: Mutable and immutable class cluster implementation / "method swizzling" question
- From: Quincey Morris <email@hidden>
- Date: Fri, 25 Mar 2011 01:41:57 -0700
On Mar 24, 2011, at 21:49, John Engelhart wrote:
> The "problem" is that with the @interface written as MYMutableArray :
> NSMutableArray", I don't inherit the MYArray methods, which I'd very much
> like to.
You have, separately, a source code problem and couple of runtime problems.
1. At the source code level, if you have:
@interface MYArray : NSArray
@interface MYMutableArray: MYArray
then the compiler will complain if you try to assign a MYMutableArray* to a NSMutableArray* variable. If you "fix" that with:
@interface MYArray : NSArray
@interface MYMutableArray: NSMutableArray
then the compiler will complain if you try to assign a MYMutableArray* to a MYArray* variable. I don't see any way to solve that directly without multiple inheritance.
You can almost get there using protocols. Here's some code I test-compiled:
> @protocol MyArrayProtocol
> @end
>
> @protocol MyMutableClassProtocol <MyArrayProtocol>
> @end
>
> typedef NSArray<MyArrayProtocol> MyArray;
> typedef NSMutableArray<MyMutableClassProtocol> MyMutableArray;
>
> ...
>
> NSArray* array = [NSArray array];
> NSMutableArray* mutableArray = [NSMutableArray array];
>
> MyArray* myArray = [MyArray array];
> MyMutableArray* myMutableArray = [MyMutableArray array];
>
> array = mutableArray;
> mutableArray = array; // incompatible pointer types
>
> myArray = myMutableArray;
> myMutableArray = myArray; // incompatible pointer types
>
> array = myArray;
> myArray = array; // oops, no warning
>
> mutableArray = myMutableArray;
> myMutableArray = mutableArray; // oops, no warning
>
> array = myMutableArray;
> myMutableArray = array; // incompatible pointer types
>
> mutableArray = myArray; // incompatible pointer types
> myArray = mutableArray; // oops, no warning
Note that class method invocations compile without error. All of the compiler warnings are as you want them, except for the assignments labeled "oops". That looks like a compiler bug, not a flaw in the protocol-based approach, I think. (Without a warning, the compiler's giving you license to add compile-time protocol conformance where it's not actually there. This is with LLVM 2.0 in Xcode 4.) Apart from that, the above gives you exactly the compile-time behavior you want, doesn't it?
All of that has absolutely nothing to do with what happens at run time ...
2. As far as the method swizzling is concerned, I'm not sure why you have to use 'class_replaceMethod' on anything but '+alloc'. If you return an object of your own class (by which I mean a private class along the lines of NSCFArray), then you can simply implement the rest of the basic methods normally, can't you? Also, you can use whatever runtime classes you want (including a super- and sub-class to get the desired code sharing, or most likely just a single class, again along the lines of NSCFArray).
The only thing this doesn't cover is what 'Class' objects your "classes" return. I'm not sure, but I think there's enough flexibility in the runtime to implement fictional classes, because I think sort of thing is used elsewhere (e.g. KVO class swizzling -- which itself defines the level of fictionality you'd have to maintain, since it works, and apps work with it).
3. As far as 'isKindOfClass' is concerned, I'd be inclined simply to override it in your subclasses, and special-case based on the run-time-introspected type of the parameter. There's no need I can see to painfully construct an actual subclass hierarchy just so you can use the standard implementation. There's also no need to reproduce the NSArray/NSMutableArray defect in your classes, unless you decide you want to -- you *could* return the semantically proper answer.
4. Incidentally, I can't find the answer to this in your original post, but why do you actually need new compile-time classes for this? What if you just added factory methods and/or alloc/inits that created objects that *claim to be* NSArray and NSMutableArray (just like NSCFArray, basically)? Once created, let them be different implementations of a concrete underlying class, but NSArray/NSMutableArray for compilation purposes. IOW, join the class cluster instead of subclassing it.
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden