![](/img/trans.png)
[英]How to conform to Objective-C protocol with readonly properties in Swift
[英]Objective-C readonly properties in a subclass
我有一个称为SuperClass的超类,它是一个只读属性。 看起来像这样:
@property (nonatomic, strong, readonly) NSArray *arrayProperty;
在子类中,我需要一个初始化程序,该初始化程序将SuperClass的实例作为参数:
- (instancetype)initWithSuperClass:(SuperClass *)superClass
我创建了一个GitHub示例项目来显示问题所在: https : //github.com/marosoaie/Objc-test-project
我无法在初始化程序中执行_arrayProperty = superClass.arrayProperty
。 我也想在SubClass中保持该属性为只读。
关于如何解决的任何想法?
我知道我可以在SubClass实现文件中的类扩展中将该属性声明为readwrite,但是我希望有比这更好的解决方案。
编辑:SuperClass.h
#import <Foundation/Foundation.h>
@interface SuperClass : NSObject
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@property (nonatomic, strong, readonly) NSString *stringProperty;
@property (nonatomic, strong, readonly) NSArray *arrayProperty;
@end
超类
#import "SuperClass.h"
@implementation SuperClass
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
_arrayProperty = dictionary[@"array"];
_stringProperty = dictionary[@"string"];
}
return self;
}
@end
SubClass.h:
#import <Foundation/Foundation.h>
#import "SuperClass.h"
@interface SubClass : SuperClass
@property (nonatomic, strong, readonly) NSString *additionalStringProperty;
- (instancetype)initWithSuperClass:(SuperClass *)superClass;
@end
子类.m:
#import "SubClass.h"
@implementation SubClass
@synthesize additionalStringProperty = _additionalStringProperty;
- (NSString *)additionalStringProperty
{
if (!_additionalStringProperty) {
NSMutableString *mutableString = [[NSMutableString alloc] init];
for (NSString *string in self.arrayProperty) {
[mutableString appendString:string];
}
_additionalStringProperty = [mutableString copy];
}
return _additionalStringProperty;
}
- (instancetype)initWithSuperClass:(SuperClass *)superClass
{
self = [super init];
if (self) {
// Doesn't work
// _stringProperty = superClass.stringProperty;
// _arrayProperty = superClass.arrayProperty;
}
return self;
}
@end
您已经暴露了一个初始化程序,该初始化程序写入该只读属性-initWithDictionary:
在您的SubClass中调用它,而不是[super init]
:
- (instancetype)initWithSuperClass:(SuperClass *)superClass {
NSDictionary *dict = @{
@"array": superClass.arrayProperty,
@"string": superClass.stringProperty,
};
self = [super initWithDictionary:dict];
if (self) {
// Nothing here.
}
return self;
}
对于只读属性有一个初始化器是很常见的,尽管使用字典并不是一个好的解决方案。 通常,我会创建:
- (instancetype)initWithArray:(NSArray *)array string:(NSString *)string;
首先,测试设置中存在一个错误@"arrayProperty"
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
是@"array"
,其中数组包含@"arrayProperty"
。
关于您的问题:
//...
@interface SuperClass : NSObject
{
@protected // this is what you want: a protected class property, accessible in subclasses, but no where else
NSString *_stringProperty;
NSArray *_arrayProperty;
}
@property (nonatomic, strong, readonly) NSString *stringProperty;
@property (nonatomic, strong, readonly) NSArray *arrayProperty;
- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@end
// SubClass.m
//...
@implementation SuperClass
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
_arrayProperty = dictionary[@"arrayProperty"]; // this was @"array", so could not work
_stringProperty = dictionary[@"stringProperty"]; // same here
}
return self;
}
@end
然后就可以了。 另外,我会写
@interface SubClass ()
@property (nonatomic, strong, readwrite) NSString *additionalStringProperty;
@end
@implementation SubClass
- (instancetype)initWithSuperClass:(SuperClass *)superClass
{
self = [super init];
if (self) {
_stringProperty = superClass.stringProperty;
_arrayProperty = superClass.arrayProperty;
}
return self;
}
因为相比@synthesize
魔术,我更喜欢类扩展中的readwrite
属性。 但这是个人观点。
有关类设计的一个主要问题仍然存在:如果(类似于您的测试设置)超类的字典不包含键,将会发生什么? 然后它不会被初始化,这不是一个好主意,因为您希望它们被初始化。 因此,如果superclass.stringProperty不为nil,则应检查子类,并为超类添加标准构造函数,以避免两个字典未初始化。
在您的SuperClass.m中:
- (instancetype)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
if (self) {
// these were always nil, check your dictionary keys
_arrayProperty = dictionary[@"arrayProperty"];
_stringProperty = dictionary[@"stringProperty"];
}
return self;
}
在您的SubClass.m中:
@interface SubClass ()
@property (strong, nonatomic) NSString * additionalStringProperty;
@property (strong, nonatomic) NSString * subClassString;
@property (strong, nonatomic) NSArray * subClassArray;
@end
@implementation SubClass
- (instancetype)initWithSuperClass:(SuperClass *)superClass
{
self = [super init];
if (self) {
_subClassString = superClass.stringProperty;
_subClassArray = superClass.arrayProperty;
}
return self;
}
我在这里尝试答案无济于事。 最终对我有用的是这个答案 ,它提到您应该直接访问成员变量(在将其声明为受保护后),如下所示:
self->_stringProperty = @"some string";
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.