Objective-C ++中的复杂类层次结构

时间:2013-09-26 16:21:35

标签: c++ ios objective-c templates inheritance

考虑以下基类:

@interface ViewBase : UIView
@property (readonly) LayerBase *myLayer;
+ (Class)myLayerClass; // _myLayer = [[[self class] myLayerClass] new];
@end

@interface LayerBase : CALayer
@property AbstractGrid *grid;
@end

class AbstractGrid
{
public:
    int rows, columns;
    virtual someMethod() = 0;
}

我有一个模板Grid类,它使用不同的单元格类型(需要AbstractGrid,因为无法创建模板Objective-C类):

template <class Cell>
class Grid : public AbstractGrid
{
public:
    Cell **cells;
    virtual someMethod() {}
}

现在我要创建一个ViewBase的子类,其类型为myLayer,也是LayerBase的子类(+myLayerClass方法也已重新定义)并使用不同的模板参数对于模型类,例如:

@interface AView : ViewBase
@property (readonly) ALayer *myLayer;
@end

@interface ALayer : LayerBase
@property Grid<GridCell> *grid;
@end

class GridCell
{
public:
    int row, column;
}

应用程序可以正常使用此方法,但编译器会向我发出有关不兼容属性类型的警告:

  

属性类型'ALayer *'与从'ViewBase'继承的类型'LayerBase *'不兼容
  属性类型'Grid *'与从'LayerBase'继承的类型'AbstractGrid *'不兼容

虽然我可以通过声明类型为id的图层属性来静音第一个警告(这不是最好的解决方案,因为我不能使用没有类型转换的点语法,我可能会犯错,编译器赢了'能够捕获):

@property (readonly) id myLayer;

我不能用C ++类型做同样的事情。将grid属性声明为void *也无济于事。

有没有一种正确的方法来处理这种情况?或者我应该简单地使用pragma来消除警告,因为我知道我在做什么?

请不要建议不要使用C ++类,因为它不是一个选项(我正在创建一组跨平台模型类以方便将来移植。)

2 个答案:

答案 0 :(得分:1)

是。不要改变返回类型。例如:

@interface LayerBase : CALayer
- (AbstractGrid *)grid;
@end


@interface ALayer : LayerBase

// ALayer's local storage and typed interface:
@property Grid<GridCell>* grid_GridCell; // << use unique selector names

// ALayer's abstract interface/overrides:
- (AbstractGrid *)grid; // << returns self.grid_GridCell

@end

答案 1 :(得分:0)

好吧,我决定删除grid @property(因为在这种情况下我不需要像KVO这样的任何属性功能),而选择好旧的getter / setter并简单地在子类中转换返回类型。 clang很聪明,允许任意getter的点语法,所以现在我没有得到任何警告。

@interface LayerBase : CALayer {
    AbstractGrid *_grid;
}
- (AbstractGrid *)grid;
- (void)setGrid:(AbstractGrid *)grid;
@end

@implementation LayerBase
- (AbstractGrid *)grid {
    return _grid;
}

- (void)setGrid:(AbstractGrid *)grid {
    _grid = grid;
}
@end

@interface ALayer : LayerBase
- (Grid<GridCell> *)grid;
@end

@implementation ALayer
- (Grid<GridCell> *)grid {
    return (Grid<GridCell> *)[super grid];
}
@end