属性类型与访问器类型不匹配(子类化时)

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】:

你的@propertyint,编译器可能弄乱了你的方法。尝试将@property 类型设置为NumberEnum,它应该可以工作(您需要将枚举定义移动到您的.h)

【讨论】:

我无法将枚举移动到基类,因为基类被用作多个子类的低音类。 @PeterM 那么你不能改变property的类型或者它在子类中的访问器。 那么,如果您的子类处理相同属性的不同类型,即使将 int 更改为枚举数,您也可能遇到一些设计问题。也许在你的ChildClass 中创建一个新属性,然后覆盖那里的value getter/setter 方法。 @Ismael 基类包含可以在不同子类之间共享的通用代码,枚举基本上是一个具有预定义的一组允许值的 int。 好吧,你问警告是关于什么的,就编译器而言,intNumberEnum 显然不是一回事。【参考方案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] 的语法糖,因此我希望在两行或两行都出现警告。但是我同意您的解决方案有效! (或者当然首先要继承的全部原因是我有多个子类,它们有一些我正在推入基类的公共代码)

以上是关于属性类型与访问器类型不匹配(子类化时)的主要内容,如果未能解决你的问题,请参考以下文章

C#属性访问器

JavaScript | 数据属性与访问器属性

6.Swift协议|扩展|访问权限|异常调试|类型转换|运算函数|ARC|类类型初试化器|值类型初始化器

访问 URLSessionConfiguration 子类的属性时无法识别的选择器

010. CSS 选择器

010.里式转换命名空间字段属性索引器