• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Redeclaring property types in mutable subclasses
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Redeclaring property types in mutable subclasses


  • Subject: Re: Redeclaring property types in mutable subclasses
  • From: Ken Thomases <email@hidden>
  • Date: Tue, 29 Mar 2011 00:54:03 -0500

On Mar 28, 2011, at 11:28 PM, Quincey Morris wrote:

> On Mar 28, 2011, at 20:05, Adam Ernst wrote:
>
>> I have a class with an array property:
>>
>> @interface Widget : NSObject {}
>> @property (retain, readonly) NSArray *gizmos;
>> @end
>>
>> I make a mutable subclass. In addition to making the array property readwrite, I also make it an NSMutableArray for convenience:
>>
>> @interface MutableWidget : Widget {}
>> @property (retain, readwrite) NSMutableArray *gizmos;
>> @end
>>
>> This triggers a warning:
>>
>> Property 'gizmos' type does not match super class 'Widget' property type
>>
>> I can understand why this is being triggered. How can I work around it? I could keep it a straight NSArray, but this is cumbersome to edit. Suggestions on how to properly model this in my code?
>
> The pattern I use is:
>
>> @interface MutableWidget : Widget {}
>> @property (retain, readwrite) NSMutableArray *mutableGizmos;
>> @end

Do either of you really mean for that property to be read-write?

I can see making a property read-write with an immutable type, and I can see (although I don't particularly like) making a read-only property return a mutable type.  (Having properties of mutable type breaks encapsulation in a big way.)  But it seems strange to me to make a read-write property of mutable type.

Especially you, Quincey, when you've made a "sibling", mutable variant of the property.  Is there really a setMutableGizmos: method?  What does it mean?

Also, if you're using -mutableArrayValueForKey: without providing the mutation accessors, then that's probably asking for grief.  Actually, you said something I didn't follow about a setter for the gizmos property, but that's read-only.  So, it's not clear to me how the proxy is supposed to mutate it (other than KVC's direct instance variable access, which I always disable).  And without either a proper setter or the mutation accessors, you've violated encapsulation.  Clients of your class can mutate your property without you being informed (unless you KVObserve your own property).

Here's what makes sense to me:

@interface Widget : NSObject {}
@property (retain, readonly) NSArray *gizmos;

// optionally, any of:
- (NSUInteger) countOfGizmos;
- (id) objectInGizmosAtIndex:(NSUInteger)index;
- (NSArray*) gizmosAtIndexes:(NSIndexSet*)indexes;
- (void) getGizmos:(Gizmo**)buffer range:(NSRange)inRange;

@end


@interface MutableWidget : Widget {}

// At least one of:
- (void) insertObject:(Gizmo*)gizmo inGizmosAtIndex:(NSUInteger)index;
- (void) insertGizmos:(NSArray *)gizmoArray atIndexes:(NSIndexSet *)indexes;

// At least one of:
- (void) removeObjectFromGizmosAtIndex:(NSUInteger)index;
- (void) removeGizmosAtIndexes:(NSIndexSet *)indexes;

// optionally, either of:
- (void) replaceObjectInGizmosAtIndex:(NSUInteger)index withObject:(id)anObject;
- (void) replaceGizmosAtIndexes:(NSIndexSet *)indexes withGizmos:(NSArray *)gizmoArray;

@end


Then, clients of MutableWidget can either directly use those mutation accessors or they can invoke [aMutableWidget mutableArrayValueForKey:@"gizmos"] and mutate that.  If you really want to wrap the latter in a convenience method, you can, but I don't think that constitutes a read-write property.

And I reiterate that one should almost always implement +(BOOL)accessInstanceVariablesDirectly { return NO; } on all one's classes.


If you're looking for guidance, I suggest contemplating what the framework classes do.  Can you think of any mutable class which changes the type of one of the base class's properties to be mutable?  Can you think of any which added a mutable variant of one of the base class's properties (as mutableGizmos is to gizmos)?  Well, frankly, can you think of any framework class that has a property of mutable type?!?

No.  Mutable subclasses should provide setters or mutation accessors.  That's the core of what they should add to the interface of the immutable super class.

Regards,
Ken

_______________________________________________

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

  • Follow-Ups:
    • Re: Redeclaring property types in mutable subclasses
      • From: Quincey Morris <email@hidden>
References: 
 >Redeclaring property types in mutable subclasses (From: Adam Ernst <email@hidden>)
 >Re: Redeclaring property types in mutable subclasses (From: Quincey Morris <email@hidden>)

  • Prev by Date: Re: Redeclaring property types in mutable subclasses
  • Next by Date: Re: UI Panel With "Pointer" On One Side
  • Previous by thread: Re: Redeclaring property types in mutable subclasses
  • Next by thread: Re: Redeclaring property types in mutable subclasses
  • Index(es):
    • Date
    • Thread