Objective C类数据结构,类引用的实例再次作为ivars

时间:2012-02-27 06:02:00

标签: objective-c data-structures recursive-datastructures cross-reference

我正在写一个Objective C中的一个类,它有一个具有相同类的实例的ivar ......

@interface State : NSObject {
NSString *name
NSSet *neighboringStates    // this is a set of State objects
}

州*加利福尼亚州将拥有包含* oregon,* washington和* nevada的* adjacentStates。 这三个国家中的每一个都有其邻国的加利福尼亚州。

我希望指针引用相同的实例,这样每个状态只实例化一次,并且在另一个状态的方法调用期间对状态的任何更改都会影响内存中的同一个对象。

这有用吗?我甚至不确定这个术语是什么,所以很难谷歌。

感谢您的帮助!

编辑:

为了让你更清楚我正在尝试做什么,我想生成状态的排列,使得每个状态只被访问一次,而置换列表中的每个下一个状态必须来自邻近/邻近状态到现在的。因此,一旦我开始在加利福尼亚州并前往俄勒冈州,因为我知道我目前的路径包含加利福尼亚州,我从我的可用州移除加州。我通过获取当前状态的adjacentStates设置并删除当前路径中的任何状态来跟踪可用状态。

3 个答案:

答案 0 :(得分:2)

创建一个Country类,该类也可用作State工厂。

因此,States不会创建其他States,而是从他们所属的Country获取它们。

同样,客户端不会创建State,而是从Country请求它们。

来自State的{​​{1}}的请求也可以验证Country在返回之前是否已正确初始化以供公众使用 - 因为您无法“简单地”初始化48个代码( State)。

答案 1 :(得分:2)

没有理由说你所描述的东西不会起作用,虽然它会在代码中设置这么长而无聊:

State * california = [State stateWithName:@"California"];
State * oregon = [State stateWithName:@"Oregon"];
State * nevada = [State stateWithName:@"Nevada"];
// And so on, forty-seven more times.
// Stick them in an array or something?
// Now use all those instances that you've just created to set up 
// the neighboring states.
[california setNeighboringStates:[NSSet setWithObjects:oregon, nevada, nil];
[oregon setNeighboringStates:[NSSet setWithObjects:washington, california, idaho, nevada, nil];
// And so on, forty-seven more times.

如果你已经获得了这样的数据,那么在应用程序的生命周期中已经修复了这些数据,你会想要将其粘贴到某种数据文件中然后取消归档在运行时。

答案 2 :(得分:1)

我不确定你的问题到底是什么。有一种名为Singleton的设计模式可确保您只能拥有给定类的一个实例。这不是你想要的,但是有一个名为Multiton的Singleton模式的变体,它为给定的密钥保存了一个类的实例(在你的例子中,是一个州名)。这就是[NSNull null](单身)或NSNumber(多声道)工作的方式:

NSLog(@"%i", [NSNull null] == [NSNull null]); // 1
NSLog(@"%i", [NSNumber numberWithInt:42] == [NSNumber numberWithInt:42]); // 1

但是这些模式很容易被滥用,如果没有它们可以解决问题可能会好得多。使所有状态指针引用同一个实例没有问题。也就是说,只有创建整个对象图的问题。如果你保持属性可变,这很容易:

State *oregon = [[State alloc] initWithName:@"Oregon"];
State *washington = [[State alloc] initWithName:@"Washington"];
[oregon setNeighbouringStates:[NSSet setWithObject:washington]];
[washington setNeighbouringStates:[NSSet setWithObject:oregon]];

等等。对您的问题更好的解决方案可能是不同的数据模型,表示相邻关系的不同方式。但这取决于您的要求。

你在评论中说你在字典中有状态。键是状态名称,值是邻居状态名称的数组?如果是这种情况,你可以这样做:

typedef State* (^StateBuilder)(NSString *stateName);

NSDictionary *input = …;
NSMutableDictionary *states = [NSMutableDictionary dictionary];

StateBuilder getState = ^(NSString *stateName) {
    State *state = [states objectForKey:stateName];
    if (!state) {
        state = [[State alloc] initWithName:stateName];
        [states setObject:state forKey:stateName];
    }
    return state;
};

for (NSString *stateName in [input allKeys]) {
    State *state = getState(stateName);
    NSMutableSet *neighbours = [NSMutableSet set];
    for (NSString *neighbourName in [input objectForKey:stateName])
        [neighbours addObject:getState(neighbourName)];
    [state setNeighbours:neighbours];
}

结果将以[states allValues]结尾。当然,块voodoo不是必需的,您可以将states字典转换为实例变量并使用常规方法而不是块。