Objective C — narrow instance variable types in subclasses?

后端 未结 4 614
无人共我
无人共我 2020-12-11 08:02

Is it possible to narrow the allowed type of an ivar in a subclass. Something like this:

@interface person: NSObject {
  NSArray *friendArray;
}

@interface         


        
相关标签:
4条回答
  • 2020-12-11 08:21

    No, you can't redeclare ivars at all. However, you can make a new method based property without making a new ivar.

    @property (nonatomic, copy) NSMutableArray* mutableFriends;
    
    @implementation MutablePerson
    
    - (NSMutableArray*)mutableFriends {
      return (NSMutableArray*)friendArray;
    }
    
    - (void)setMutableFriends:(NSMutableArray*)friends {
      self.friendsArray = [friends mutableCopy];
    }
    
    @end
    
    0 讨论(0)
  • 2020-12-11 08:27

    I ended overriding the setter to assert that the object being set is of the appropriate type, and creating a new read-only getter, like this:

    @interface MutablePerson {
    }
    
    @property (readonly) NSMutableArray *mutableFriendArray;
    
    @implementation MutablePerson
    
    -(NSMutableArray *) mutableFriendArray {
      NSMutableArray *ret = (NSMutableArray *)[super friendArray];
      NSAssert ([ret isKindOfClass: [NSMutableArray class]], @"array should be mutable");
      return ret;
    }
    
    -(void) setFriendArray: (NSMutableArray *) array {
      NSAssert ([array isKindOfClass: [NSMutableArray class]], @"array should be mutable");
      [super setFriendArray: array];
    }
    
    0 讨论(0)
  • 2020-12-11 08:32

    If the compiler says 'no' then that's your answer. I would use accessors:

    //Person
    -(NSArray *)friends;
    
    
    //MutablePerson
    -(void)addFriend:(person *)friend;
    

    In the MutablePerson you could declare another array to store friends or you could access the ivar directly in addFriend::

    -(void)addFriend:(person *)friend
    {
        _friendsArray = [_friendsArray arrayByAddingObject: friend];
    }    
    

    Accessing ivars directly isn't smart. I would reconsider your class design. What's the rationale for having a mutable and immutable versions of person?

    0 讨论(0)
  • 2020-12-11 08:42

    @class doesn't make sense at all... it should be @interface. So the first error is purely syntactical.

    And no, you cannot change the type of an ivar. And that's for a good reason: Narrowing it down (as you do) can't work, because the parent class might rely on a different implementation. Widening it can't work as well (mainly for the analogous reason.

    0 讨论(0)
提交回复
热议问题