use*_*037 10 inheritance properties objective-c redeclaration
我对财产重新申报表示怀疑
概述:
注意事项: - 内存管理= ARC(自动引用计数)
题:
代码:(在单独的文件中)
啊
#import<Foundation/Foundation.h>
@interface A : NSObject
@property (readonly) int n1;
- (void) display;
@end
Run Code Online (Sandbox Code Playgroud)
上午
#import "A.h"
@implementation A
@synthesize n1 = _n1;
- (void) display
{
printf("_n1 = %i\n", _n1); //I expected _n1 and self.n1 to display the same value
printf("self.n1 = %i\n\n", self.n1); //but they seem to display different values
}
@end
Run Code Online (Sandbox Code Playgroud)
BH
#import"A.h"
@interface B : A
@property (readwrite) int n1;
@end
Run Code Online (Sandbox Code Playgroud)
BM
#import"B.h"
@implementation B
@synthesize n1 = _n1;
@end
Run Code Online (Sandbox Code Playgroud)
test.m
#import"B.h"
int main()
{
system("clear");
B* b1 = [[B alloc] init];
b1.n1 = 20;
[b1 display]; //Doubt - my expected behavior is different from actual behavior
return(0);
}
Run Code Online (Sandbox Code Playgroud)
预期行为:
_n1 = 20
self.n1 = 20
Run Code Online (Sandbox Code Playgroud)
实际行为:
_n1 = 0
self.n1 = 20
Run Code Online (Sandbox Code Playgroud)
有两种方法可以解决这个问题.在这两种情况下,您都不会调用@synthesize子类.我很惊讶为你编译.我希望像"属性'n1'尝试使用在超类'A'中声明的ivar'_n1'这样的错误".在任何情况下,它绝对不是你真正能做的事情,这就是为什么你会看到奇怪的行为.(我记得为什么你没有看到这个错误;这是因为单独的编译单元.你只是用不同的ivars结束.)
首先,你需要了解@dyanmic.这是一种告诉编译器的方法"是的,我知道你没有在这里看到所需方法的实现;我保证它会在运行时存在." 在子类中,您将使用@dynamic让编译器知道可以继承n1.
@implementation B
@dynamic n1;
@end
Run Code Online (Sandbox Code Playgroud)
现在,您需要提供该setN1:方法.IMO,子类不应该搞乱他们的超类的ivars,所以我赞成合成的ivars被标记的事实@private.在一瞬间,我会告诉你如何撤消,但现在让我们处理我的首选解决方案:
setN1:作为私有方法A.B.啊
@interface A : NSObject
@property (readonly) int n1;
- (void) display;
@end
Run Code Online (Sandbox Code Playgroud)
上午
#import "A.h"
@interface A () // Private class extension, causes setN1: to be created but not exposed.
@property (readwrite) int n1;
@end
@implementation A
@synthesize n1 = _n1;
- (void) display {
...
}
@end
Run Code Online (Sandbox Code Playgroud)
BH
#import "A.h"
@interface B : A
@property (readwrite) int n1; // Tell the world about setN1:
@end
Run Code Online (Sandbox Code Playgroud)
BM
#import "B.h"
@implementation B
@dynamic n1; // Yes compiler, setN1: exists. I promise.
@end
Run Code Online (Sandbox Code Playgroud)
现在,有些人认为子类可以搞乱他们的超类的ivars.那些人是错的(好吧,恕我直言......)但是在ObjC中是可能的.你只需要申报ivar @protected.这是您直接声明ivars时的默认设置@interface(您不应再这样做的原因之一).它看起来像这样:
啊
@interface A : NSObject {
int _n1;
}
...
Run Code Online (Sandbox Code Playgroud)
Am - 删除使超类中的n1可写的额外类扩展.
Bh - 没有变化
BM
@implementation B
@dynamic n1;
- (void)setN1:(int)n1 {
_n1 = n1;
}
@end
Run Code Online (Sandbox Code Playgroud)