Какао: Словарь с перечислимыми ключами?

Используя Ваш пример Стека, Вы действительно не должны должны быть представлять любые внутренние работы модульному тесту это. Повторяя, что сказали другие, необходимо не стесняться иметь как много закрытых методов по мере необходимости, но только тестировать через общедоступный API.

[Test]
public void new_instance_should_be_empty()
{
  var stack = new Stack();

  Assert.That(stack.IsEmpty(), Is.True);
}

[Test]
public void single_push_makes_IsEmpty_false()
{
  var stack = new Stack();

  stack.Push("first");

  Assert.That(stack.IsEmpty(), Is.False);
}

Используя комбинацию продвижения и сования можно моделировать все поведение класса Стека, потому что это - единственный способ, которым пользователь должен взаимодействовать с ним. Вам не нужны никакие приемы, потому что необходимо только тестировать то, что могут использовать другие.

[Test]
public void three_pushes_and_three_pops_results_in_empty_stack()
{
  var stack = new Stack();

  stack.Push("one");
  stack.Push("two");
  stack.Push("three");
  stack.Pop();
  stack.Pop();
  stack.Pop();

  Assert.That(stack.IsEmpty(), Is.True);
}
24
задан Rui Peres 20 August 2012 в 08:43
поделиться

4 ответа

Поскольку перечисления являются целыми числами, вы можете обернуть перечисление в NSNumber. Когда вы добавляете / извлекаете что-то на / из карты, вы передаете перечисление в конструктор NSNumber ...

Предполагая, что у вас есть перечисление типа ...

enum ETest {
    FOO, BAR
};

Вы можете использовать его в NSDictionary, как это. ..

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Foo!" forKey:[NSNumber numberWithInt: FOO]];
NSLog(@"getting value for FOO -> %@", 
      [dict objectForKey: [NSNumber numberWithInt: FOO]]);  
[dict release]; 
30
ответ дан 28 November 2019 в 22:23
поделиться

With VoidPointer's suggestion, it may be better to use NSValue for those times when enums turn out not to be integers (such as when -fshort-enums is in play, which should be never as you'd probably break compatibility with Foundation).

NSValue *value = [NSValue value: &myEnum withObjCType: @encode(enum ETest)];

That's not going to add much here but gives you the general "I want to use in a collection class" technique.

Notice that with modern compilers you can tell enums to use a fixed underlying type. This means you can control what storage is used for the enum, but as the above solution is general it still applies even when you know this.

28
ответ дан 28 November 2019 в 22:23
поделиться

Дальнейшее расширение предложения Грэма Ли ...

Вы можете использовать категорию objective-c , чтобы добавить метод в NSMutableDictionary, который позволяет вам добавьте значение с ключом вашего типа, отличного от NSObject. Это избавляет ваш код от синтаксиса упаковки / развертывания.

Опять же, предполагая

enum ETest { FOO, BAR };

Сначала мы добавляем конструктор convince в NSValue:

@interface NSValue (valueWithETest)
+(NSValue*) valueWithETest:(enum ETest)etest; 
@end

@implementation NSValue (valueWithETest)
+(NSValue*) valueWithETest:(enum ETest)etest
{
    return [NSValue value: &etest withObjCType: @encode(enum ETest)];
}
@end

Затем мы добавим поддержку enum ETest в NSMutableDictionary

@interface NSMutableDictionary (objectForETest)
-(void) setObject:(id)anObject forETest:(enum ETest)key;
-(id) objectForETest:(enum ETest)key;
@end

@implementation NSMutableDictionary (objectForETest)
-(void) setObject:(id)anObject forETest:(enum ETest)key
{
    [self setObject: anObject forKey:[NSValue valueWithETest:key]];
}
-(id) objectForETest:(enum ETest)key
{
    return [self objectForKey:[NSValue valueWithETest:key]];
}
@end

] Таким образом, исходный пример можно преобразовать в

NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject: @"Bar!" forETest:BAR];
NSLog(@"getting value Bar -> %@", [dict objectForETest: BAR]);      
[dict release];

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

9
ответ дан 28 November 2019 в 22:23
поделиться

перечисления не соответствуют NSCopying

Это преуменьшение; перечисления ни с чем не «согласуются», поскольку они не являются объектами; это примитивные значения C, которые взаимозаменяемы с целыми числами. Это настоящая причина, по которой их нельзя использовать в качестве ключей. Ключи и значения NSDictionary должны быть объектами. Но поскольку перечисления являются целыми числами, их можно просто обернуть в объекты NSNumber . Это, вероятно, самый простой вариант.

Другой вариант, если перечисления непрерывны от 0 до некоторого числа (т.е. вы не устанавливали никаких значений вручную), заключается в том, что вы можете использовать NSArray , где индекс представляет значение ключевого перечисления. (Любые «отсутствующие» записи должны быть заполнены NSNull .)

7
ответ дан 28 November 2019 в 22:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: