Sean Fraser
Sean Fraser

Reputation: 352

Re-Casting a Property in Subclasses

I have a set up where I have a hierarchy of view types with an equivalent hierarchy of model types. The set up is as follows:

The node model / data:

@interface GenericNode : NSObject
//blah blah blah
@end
@interface ShapeNode : GenericNode
//more blah
@end

the nodeViews, which will always receive an equivalently typed node as its model:

@interface GenericNodeView : UIView
@property (nonatomic, strong) GenericNode * model;
@end
@interface ShapeNodeView : GenericNodeView
@end

However, the problem here is that the type of the model is always retained as the abstract superclass, forcing me to cast it every single time I want to access methods of properties of the subclasses.

Is there a way to recast class properties such that exampleShapeNodeView.model always returns an instance of ShapeNode and so on?

I have tried custom accessor methods such as

@interface GenericNodeView : UIView
@property (nonatomic, strong) GenericNode * model;
-(GenericNode *)myModel;
@end
@interface ShapeNodeView : GenericNodeView
-(ShapeNode *)myModel;
@end

//in genericNodeView implementation
-(GenericNode *)myModel{
  return (GenericNode *) self.model;
}

//in shapeNodeView implementation
-(ShapeNode *)myModel{
  return (ShapeNode *) self.model;
}

but calling [exampleShapeNodeView myModel] still returns a GenericNode;

Upvotes: 2

Views: 682

Answers (3)

jwj
jwj

Reputation: 521

The code isn't "wrong" with all that casts, it just "feels" wrong to you. While there may be a code way to do what you want to do without Xcode complaining, you might consider changing the design a bit.

Of course, one way to go is to just make everything id type and then you can call whatever methods on the objects you want, but I'm guessing you don't want to do that.

Also, since you want to arrange the views in a view hierarchy I'm guessing that you want to reuse logic between them, i.e., classic object subclassing.

You might consider just putting the getter and setters on the 'leaf' classes, e.g., the classes in the hierarchy that don't have any children. This way you can make the signature as specific as you want and not need to cast things around, and since they aren't in the upper level classes you won't run into name clashes. I'll bet that the logic you want to leave in the parent classes is common in the sense that it's providing generic functions for the view, rather than logic that acts on the model.

Upvotes: 0

Chris Trahey
Chris Trahey

Reputation: 18290

I just tested this out, and it worked great for me:

In the child class, redeclare with the @property:

@interface GenericNodeView : UIView
@property (nonatomic, strong) GenericNode * model;
@end
@interface ShapeNodeView : GenericNodeView
@property (nonatomic, strong) ShapeNode * model;
@end

You need to re-@synthesize as well, but there were no complaints by my Xcode (4.3.3)

Upvotes: 5

Dustin
Dustin

Reputation: 6803

Make another variable and do ShapeNode *anotherVariable = (ShapeNode *) someVariable

Upvotes: 0

Related Questions