How to change a property class in sub class in Objective-C

0

I am trying to re-write some code of old project, and ideally I want to achieve below code style, but I got a lot of compile error saying dataModel don't have getLineColor method.

The abstract question is, can I change an inherited object A's class in sub view controller to a sub class A2, while the object A in parent view controller is class A1 that is the super class of A2, and how can I do it correctly? Thank in advance.

Update: I compile it, but I have met another run time error, I tried to overwrite the setter of dataModel in sub view controller. How to correctly write the setDataModel in sub class?

@implementation SubViewController
#pragma mark - setter of dataModel
- (void)setDataModel:(ChartModel *)dataModel { // it stucks at this func name
@end

error trace is

[SubChartViewController setDataModel:](self=0x00000000, _cmd=0x00000000, dataModel=0x00000031) + 12 at BDPAxisChartViewController.m:295, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0xbf774ffc)

EDIT:

@interface ChartModel : NSObject
-(BOOL)chartModelhasData;
@end

@interface LineChartModel : chartModel
-(void)getLineColor;
@property (nonatomic, strong) NSArray* seriesNameArray;
@end

@interface ChartViewController: UIViewController
@property (nonatomic, strong) ChartModel *dataModel;
-(void)layoutChartCanvas;
@end

@implementation ChartViewController
-(void)layoutChartCanvas {
    if ([self.dataModel chartModelhasData]) {
        self.view.hidden = NO;
    }
}
@end

@interface LineChartViewController : ChartViewController
// pay attension here, same name but a sub class of chartModel
@property (nonatomic, strong) LineChartModel *dataModel; 
-(void)drawLine;
@end

@implementation LineChartViewController
-(void)drawLine {
    UIColor *color = [self.dataModel getLineColor];
    [self drawLine];
    NSArray *tempArray = [self.dataModel.seriesNameArray copy];
}
@end
objective-c
asked on Stack Overflow Apr 10, 2015 by Wingzero • edited Apr 10, 2015 by Wingzero

2 Answers

1

One thing you could do is declare a LineChartModel variable and not property and @synthesize dataModel to that ivar:

@interface LineChartViewController: ChartViewController {
     LineChartModel *_lineChartModel;
}
-(void)drawLine;
@end

@implementation LineChartViewController
synthesize dataModel = _lineChartModel;
....

So from the outside it looks like you have a ChartModel, but inside the class you have LineChartModel. You will have to apply changes to _lineCharModel directly inside your class.

HOWEVER this is NOT my definition of better OOP!!! There's clearly a fault with the design if you need to cast your variables in subclass.


Another option I discovered after pasting this code into the editor is just use self.variable (which by the way, you should've already been doing).

@interface ChartModel : NSObject
- (BOOL)chartModelhasData;
@end

@interface LineChartModel : ChartModel
- (UIColor *)getLineColor;
@end

@interface ChartViewController: UIViewController
@property (nonatomic, strong) ChartModel *dataModel;
- (void)layoutChartCanvas;
@end

@implementation ChartViewController
- (void)layoutChartCanvas {
    if ([self.dataModel chartModelhasData]) {
        self.view.hidden = NO;
    }
}
@end

@interface LineChartViewController : ChartViewController
// pay attension here, same name but a sub class of chartModel
@property (nonatomic, strong) LineChartModel *dataModel;
- (void)drawLine;
@end

@implementation LineChartViewController
- (void)drawLine {
    UIColor *color = [self.dataModel getLineColor];
    [self drawLine];
}
@end
answered on Stack Overflow Apr 10, 2015 by Lord Zsolt • edited Apr 10, 2015 by Lord Zsolt
1

Probably you want to say:

Can I change the class C of a property already declared in a base class in a subclass to a subclass of C?

This is the set-up

@interface PropertyClass : NSObject
@end

@interface PropertySubclass : PropertyClass
- (void)method;                              // Additional method
@end

@interface HolderClass : NSObject
@property PropertyClass *property;           // Property is of base class
@end

@implementation HolderClass
@end

@interface HolderSubclass : HolderClass
@property PropertySubclass *property;        // Property is of subclass
@end

I have no problem to access the property subclass' method in the holder's subclass:

@implementation HolderSubclass
- (void)useIt
{
  [self.property method]; // No error or warning
}
@end

In addition to my comment below, I suspect that something like this happens:

// Create a subclass' object
HolderSubclass *object1 = [HolderSubclass new]; 
…

// Refer this object from a reference that is typed to HolderClass
// **This applies to all usages of self inside @implementation HolderClass**
HolderClass *object2 = object1; // Of course more complex

id value = [object2 method]; // Error

This error is correct. If this is the error, it is solvable. But first we have to clarify that.


BTW: This has nothing to do with better OOP. First of all this is a problem of class based programming languages, not of object orientated programming languages. Second I cannot see that this set-up will break a rule of class based or object orientated programming, esp. it fulfills Liskov's rule.

http://en.wikipedia.org/wiki/Liskov_substitution_principle

answered on Stack Overflow Apr 10, 2015 by Amin Negm-Awad • edited Apr 10, 2015 by Amin Negm-Awad

User contributions licensed under CC BY-SA 3.0