属性类型与访问器类型不匹配(子类化时)
Posted
技术标签:
【中文标题】属性类型与访问器类型不匹配(子类化时)【英文标题】:Type of property does not match type of accessor (when subclassing) 【发布时间】:2012-11-23 14:02:46 【问题描述】:好的,我知道这个主题之前在 SO 上已经多次提及,但是在检查了几个这样的问题之后,没有人谈到我在覆盖子类中的基类 getter/setter 时遇到的问题。
我的基类是:
#import <Foundation/Foundation.h>
@interface BaseClass : NSObject
@property (nonatomic, assign) int value;
@end
@implementation BaseClass
@synthesize value;
@end
因此,我希望子类充当垫片并将“值”从 int 映射到子类中的枚举:
#import <UIKit/UIKit.h>
#import "BaseClass.h"
typedef enum
zero = 0,
one,
two,
three,
four
NumberEnum;
@interface ChildClass : BaseClass
-(void)setValue:(NumberEnum)newValue;
-(NumberEnum)value;
@end
@implementation ChildClass
-(void)setValue:(NumberEnum)newValue
[super setValue:(int)newValue];
NSLog(@"Child Setter");
-(NumberEnum)value
NSLog(@"Child Getter");
return (NumberEnum)[super value];
@end
我使用以下代码测试此代码:
ChildClass* fred = [[ChildClass alloc] init];
NumberEnum barney;
fred.value = one;
barney = fred.value;
barney = [fred value];
XCode (4.5.2) 生成警告
属性“值”的类型与访问器“值”的类型不匹配
在这一行只:
barney = fred.value;
运行代码时,我看到了 Child Setter 和 Getter 的日志消息。那么我应该怎么做才能消除这个警告,为什么我首先得到它?
【问题讨论】:
【参考方案1】:你的@property
说int
,编译器可能弄乱了你的方法。尝试将@property
类型设置为NumberEnum
,它应该可以工作(您需要将枚举定义移动到您的.h)
【讨论】:
我无法将枚举移动到基类,因为基类被用作多个子类的低音类。 @PeterM 那么你不能改变property
的类型或者它在子类中的访问器。
那么,如果您的子类处理相同属性的不同类型,即使将 int 更改为枚举数,您也可能遇到一些设计问题。也许在你的ChildClass
中创建一个新属性,然后覆盖那里的value
getter/setter 方法。
@Ismael 基类包含可以在不同子类之间共享的通用代码,枚举基本上是一个具有预定义的一组允许值的 int。
好吧,你问警告是关于什么的,就编译器而言,int
和 NumberEnum
显然不是一回事。【参考方案2】:
违规行:
barney = fred.value;
告诉编译器你想使用属性value
。由于您的子类没有定义它,它会上升到基类。它发现 value
的类型不同导致警告。
解决方案是将您的属性写为:
@property (nonatomic, assign) int value;
枚举为:
enum
zero = 0,
one,
two,
three,
four
;
typedef int NumberEnum;
这样合成的属性方法和您自己的实现使用相同的数据类型。您可以使用符号值并且没有警告。
我建议改用 NSUInteger
,因为它是 64 位友好的。
当然,如果您只是在基类中将属性定义为NumberEnum
,那就更好了。
【讨论】:
fred.value 和 [fred value] 调用都通过子类中定义的 getter。我的理解是,fred.value 语法实际上是隐含 [fred value] 的语法糖,因此我希望在两行或两行都出现警告。但是我同意您的解决方案有效! (或者当然首先要继承的全部原因是我有多个子类,它们有一些我正在推入基类的公共代码)以上是关于属性类型与访问器类型不匹配(子类化时)的主要内容,如果未能解决你的问题,请参考以下文章
6.Swift协议|扩展|访问权限|异常调试|类型转换|运算函数|ARC|类类型初试化器|值类型初始化器