Возврат изменяемых и возвращаемых неизменяемых (не членов) объектов - PullRequest
8 голосов
/ 13 июня 2011

Я едва ли когда-либо видел, чтобы использовался второй, и мне интересно, почему?

  • И не будет нарушить поддержку для ситуаций, где ожидается NSArray (так как это подкласс).
  • И не будет нарушать инкапсуляцию , раскрывая изменяемые внутренние компоненты.

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

  • На самом деле является изменяемым.Приглушение звука безопасно здесь, поэтому зачем это нужно ?
  • Не нужно вызывать [[[foo fooBar] mutableCopy] autorelease], что без необходимости выделяет дополнительную память и без необходимости тратит время .

Вот варианты метода:

- (NSArray *)fooBar {
    NSMutableArray *fooArray = [NSMutableArray array];
    //populate fooArray
    return fooArray;
}

- (NSMutableArray *)fooBar {
    NSMutableArray *fooArray = [NSMutableArray array];
    //populate fooArray
    return fooArray;
}

Я спрашиваю, как В моем проекте есть несколько методов стот же шаблон .
И в в большинстве случаев возвращаемый массив будет впоследствии изменен (объединены, отредактированы и т. д.).
Так что я думаю должно быть в полном порядке , чтобы вернуть NSMutableArrays, но кажется, никто этого не делает .

NSMutableArray, NSMutableSet, NSMutableDictionary ... это в основномта же сделка.

Ответы [ 3 ]

4 голосов
/ 13 июня 2011

Для объяснения использования изменяемого и неизменяемого ознакомьтесь с документацией Apple по Изменяемость объекта .

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

Итак, у вас может быть правильное место для возврата изменяемого массива (я не знаю), но вы видите, что большая часть кода передает неизменяемые массивы, потому что он полностью инкапсулирует их переменные и их реализации.

2 голосов
/ 13 июня 2011

Полагаю, первый вариант был предпочтительнее, потому что предпочтительным был полиморфизм.

В любом случае оба метода возвращают экземпляр NSMutableArray, с той лишь разницей, что первый скрывает этот факт от вызывающей стороны. Другими словами, первый вариант не безопаснее второго. По сути, он использует полиморфизм, чтобы сообщить вызывающей стороне, что может быть возвращен любой тип NSArray. Если вам нужна такая гибкость в вашем коде, у него определенно есть свои преимущества. (например, если однажды по какой-либо причине вам понадобится вернуть пользовательский подкласс NSArray, ваш код не сломается на этом уровне).

Однако вы, кажется, предпочитаете сообщать намерение вызывающей стороне - то есть, что вы на самом деле возвращаете изменяемые массивы - что тоже нормально. Чтобы все были довольны (если что-то есть ...), я предлагаю переименовать 2-й метод в:

- (NSMutableArray *)mutableFooBar {
    NSMutableArray *fooArray = [NSMutableArray array];
    //populate fooArray
    return fooArray;
}

В качестве примечания, я думаю, что следующее является несколько более эффективным способом преобразования существующего неизменяемого массива в изменяемый:

NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:fooArray];

(поправьте меня, если я ошибаюсь в этом предположении).

Надеюсь, это ответит на ваш вопрос ...

0 голосов
/ 13 июня 2011

Наличие метода, возвращающего изменяемый экземпляр, выглядит подозрительно.

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

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

- (void)populateFooBars:(NSMutableArray *)array;

Таким образом, ясно, что изменчивость результата является преднамеренной.

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