Objective c 许多只读属性,何时初始化它们?
我有一个类,它有5个属性,不应该被其他类(以及包含更多属性的子类)修改。我想将这些属性设置为只读,但随后必须编写monsterObjective c 许多只读属性,何时初始化它们?,objective-c,macos,cocoa,properties,Objective C,Macos,Cocoa,Properties,我有一个类,它有5个属性,不应该被其他类(以及包含更多属性的子类)修改。我想将这些属性设置为只读,但随后必须编写monster-init…来为所有这些属性提供值。 当然,我可以直接编辑IVAR,但我不想在构造函数中获取值,因为我想从StackExchange API中获取这些值。在这里,将其划分为工厂类似乎更合适 tl;dr:如何在没有异常长构造函数的情况下初始化factory类的只读属性 这可能是一个设计错误。如果是这样,请添加一个建议不同方法的答案,因为本项目的重点是了解设计。通常,在这种情
-init…
来为所有这些属性提供值。当然,我可以直接编辑IVAR,但我不想在构造函数中获取值,因为我想从StackExchange API中获取这些值。在这里,将其划分为工厂类似乎更合适 tl;dr:如何在没有异常长构造函数的情况下初始化factory类的只读属性
这可能是一个设计错误。如果是这样,请添加一个建议不同方法的答案,因为本项目的重点是了解设计。通常,在这种情况下,您将使它们公开为只读,但私下为readwrite。您可以通过添加一个类扩展(在.m顶部的无名类别)来完成此操作,您可以在不使用只读分类器的情况下重新定义属性
// MyClass.h
@interface MyClass
@property (nonatomic, readonly) NSInteger myProperty;
@end
// MyClass.m
@interface MyClass () // Note the ()
@property (nonatomic) NSInteger myProperty;
@end
现在,在您的类中,您可以编写属性,但外部人员只能读取它。您不能同时拥有它。据我所知,Objective-C没有“friend”成员的概念,即只有特定类才能访问的成员。因此,您唯一的选择是创建公共只读属性并在构造函数中设置它们的值。本质上,您的类可以被视为不可变的。是的,init方法可能会很长,但这要归咎于Objective-C的冗长。这仍然是正确的设计选择 MyClass.h:
@interface MyClass : NSObject
@property (copy, readonly, nonatomic) NSString *value1;
@property (assign, readonly, nonatomic) NSInteger value2;
- (instancetype)initWithValue1:(NSString *)value1 value2:(NSInteger)value2;
@end
MyClass.m:
@implementation MyClass
- (instancetype)initWithValue1:(NSString *)value1 value2:(NSInteger)value2
{
self = [super init];
if (self)
{
_value1 = value1;
_value2 = value2;
}
return self;
}
@end
您可能还想考虑使用JeTeg的产品,因为它有重构工具,可能有助于从属性创建init方法(虽然我自己还没有这样做)。
您可以只用一个参数构造构造函数(NSARDATA或NSCORDEX,字典似乎不太喜欢键),并以定义的顺序或使用定义的键发送所有5个属性值(因为您将仅在工厂中初始化对象,所以您只需要在一个位置执行正确的顺序)。在这种情况下,如果属性数量增加,则无需重命名构造函数方法并添加越来越多的参数名。此外,您还可以简单地使用
setVale:forKey:
方法,无论属性是否为只读。有两种方法,您可能试图将这两种方法强制合并到一个模型(物理对象):
1) 如果基址提供存储(例如ivars),则值属于初始值设定项。就这么简单-确保这些值是为您的理智而只读的
2) 延迟初始化。你的帖子表明这是执行的理想方式。答案是存储是一个实现细节。让您的IVAR由类存储,并在加载时写入
实际上,您希望重用您的程序,并避免创建可怕的层次结构和依赖继承进行重用。考虑您的5个属性是如何被抽象的——这将是由一个或多个辅助类(例如,提供这些属性)采用的。通过这种方式,您可以延迟加载、复制、使用初始化或许多其他方法
然后,您的“子类”将只有一个属性,其中包含一个表示“基本5属性”的对象。子类不需要5个参数。它们只需要一个
id
参数。同样,一个实现(采用协议)可以存储属性,另一个实现可以根据需要加载属性。无论哪种方式,都可以方便地将一组公共数据或接口打包成一个类型(类或协议)。如果您希望factory类能够更新一般的只读属性,并且希望避免异常长的init
方法和令人眼花缭乱的参数数组,Objective-C中的典型解决方案不美观,但包括定义一个.h类类别(仅由factory类使用),该类别公开其他私有或只读属性
例如,考虑您的<代码>自定义对象< /> >定义如下:
// CustomObject.h
#import <Foundation/Foundation.h>
@interface CustomObject : NSObject
@property (nonatomic, readonly) NSUInteger identifier; // public interface is readonly
@end
然后,您可以定义仅由factory类使用的类别标题,该标题公开了标识符的CustomObject
属性是读写:
// CustomObject+Factory.h
#import "CustomObject.h"
@interface CustomObject (Factory)
@property (nonatomic, readwrite) NSUInteger identifier;
@end
如果你看一下
,你会看到同一概念的一个稍微不同的应用程序,其中他们揭示了状态
属性是读写
(否则它看起来是只读
)。谢谢你的回复,但是工厂类将是局外人。@11684:那么,除非我误解了你的问题,否则你不会真的希望这些属性是只读的。只有工厂才能修改它们。但是如果你说在这种情况下我不应该让它们成为只读的,我会接受你的建议。请阅读问题的最后一段。@11684这是正确的。从API接收数据的典型模式是类具有类似于updateWithDictionary:
的方法。数据类将解析数据,将其分配给属性,然后这些属性只能在类外部读取。请在示例中更具体一点。什么样的工厂类初始化什么样的对象?工厂类在Objective-C中并不常见,所以可能这就是问题所在。只需在.h中执行readonly,在.m中执行readwrite。好像是你想要的。我现在不在电脑前,所以今天晚些时候我会试试,但它似乎正是我想要的。
// CustomObject+Factory.h
#import "CustomObject.h"
@interface CustomObject (Factory)
@property (nonatomic, readwrite) NSUInteger identifier;
@end