Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 许多只读属性,何时初始化它们?_Objective C_Macos_Cocoa_Properties - Fatal编程技术网

Objective c 许多只读属性,何时初始化它们?

Objective c 许多只读属性,何时初始化它们?,objective-c,macos,cocoa,properties,Objective C,Macos,Cocoa,Properties,我有一个类,它有5个属性,不应该被其他类(以及包含更多属性的子类)修改。我想将这些属性设置为只读,但随后必须编写monster-init…来为所有这些属性提供值。 当然,我可以直接编辑IVAR,但我不想在构造函数中获取值,因为我想从StackExchange API中获取这些值。在这里,将其划分为工厂类似乎更合适 tl;dr:如何在没有异常长构造函数的情况下初始化factory类的只读属性 这可能是一个设计错误。如果是这样,请添加一个建议不同方法的答案,因为本项目的重点是了解设计。通常,在这种情

我有一个类,它有5个属性,不应该被其他类(以及包含更多属性的子类)修改。我想将这些属性设置为只读,但随后必须编写monster
-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