Объективная структура данных класса C, экземпляры классов ссылаются друг на друга как ivars - PullRequest
1 голос
/ 27 февраля 2012

Я пишу класс в Objective C, в котором есть ивар с экземплярами того же класса ...

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

Штат * В Калифорнии * соседние штаты содержат * oregon, * вашингтон и *Невада.Каждое из этих трех состояний имеет среди своих соседних штатов * Калифорнию.

Я хочу, чтобы указатели ссылались на одни и те же экземпляры, чтобы каждое состояние создавалось только один раз, а любые изменения состояния во время вызова метода в другомсостояние будет влиять на тот же объект в памяти.

Это работает?Я даже не уверен, что термин для этого, поэтому трудно гуглить это.

Я ценю вашу помощь!

РЕДАКТИРОВАТЬ:

Чтобы дать вам больше ясности в том, что я пытаюсь сделать, я хотел бы генерировать перестановки состояний так, чтобыкаждое состояние посещается только один раз, и каждое следующее состояние в переставленном списке должно быть из соседнего / смежного состояния в текущее.Так что, как только я начну в Калифорнии и поеду в Орегон, так как я знаю, что мой текущий путь содержит Калифорнию, я удаляю Калифорнию из моих доступных штатов.Я отслеживаю доступные состояния, беря набор соседних состояний текущего состояния и удаляя все состояния моего текущего пути.

Ответы [ 3 ]

2 голосов
/ 27 февраля 2012

Нет причин, по которым то, что вы описываете, не будет работать, хотя будет долго и скучно настраивать все это в коде:

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 голосов
/ 27 февраля 2012

Создайте класс Country, который также служит фабрикой State.

Таким образом, States не создают других States, они получают их от Country, к которому они принадлежат.

Аналогично, клиенты не создают State s, а запрашивают их у Country.

Запросы на State s от Country также могут подтвердить, что State правильно инициализирован для публичного использования перед его возвратом - потому что вы не можете "просто" инициализировать 48 кодовых кулонов (neighboringStates).

1 голос
/ 27 февраля 2012

Я не уверен, что именно ваш вопрос. Существует шаблон проектирования Singleton, который гарантирует, что у вас может быть только один экземпляр данного класса. Это не совсем то, что вам нужно, но есть вариант шаблона Singleton, называемый Multiton, который хранит один экземпляр класса для данного ключа (в вашем случае, имя состояния). Вот как работают [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 в переменную экземпляра и использовать обычный метод вместо блока.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...