Цель C: объяснение метода класса - PullRequest
4 голосов
/ 15 июня 2011

Как часть моего процесса перехода от C ++ к Objective-C, я интенсивно читаю книгу Какао и Objective C Up and Running. 1003 *

это строка, которая не имеет смысла для меня с моим текущим уровнем знаний:

Это объявление метода класса + (Photo*) photo;.

Может кто-нибудь объяснить мне причину, пожалуйста, почемуавтор решил для метода (Photo*) photo; объявить его как метод класса вместо метода экземпляра ?

У меня есть теория, что метод экземпляраэто что-то вроде функции-члена класса , и этот метод класса похож на статическую функцию в C ++.Но это все еще не отвечает на мой вопрос.

Вот код объявления:

#import <Foundation/Foundation.h>


@interface Photo : NSObject{

    NSString* caption;
    NSString* photographer;    
}

+ (Photo*) photo;

- (NSString*) caption;
- (NSString*) photographer;

- (void) setCaption: (NSString*)input;
- (void) setPhotographer: (NSString*)input;

@end

Код реализации следующий:

#import "Photo.h"


@implementation Photo

- (id)init
{
    self = [super init];
    if (self) {
        [self setCaption:@"Default Caption"];
        [self setPhotographer:@"Default Photographer"];
    }

    return self;
}


+ (Photo*) photo {
    Photo* newPhoto = [[Photo alloc] init];
    return [newPhoto autorelease];
}


- (NSString*) caption {
    return caption;
}


- (NSString*) photographer {
    return photographer;
}


- (void) setCaption:(NSString *)input {
    [caption autorelease];
    caption = [input retain];
}


- (void) setPhotographer: (NSString *)input {
    [photographer autorelease];
    photographer = [input retain];
}


- (void)dealloc
{
    [self setCaption:nil];
    [self setPhotographer:nil];

    [super dealloc];
}

@end

Ответы [ 6 ]

7 голосов
/ 15 июня 2011

Метод + (Photo*) photo - это Фабричный метод , который инкапсулирует детали создания объекта класса Photo.

Фабричный метод обеспечивает инкапсуляция и позволяет объекту быть запрошенным без неразрывного связь с актом творения.

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

В API Objective-C является обычной практикой предоставлять фабричные методы в классах, которые возвращают автоматически выпущенные объекты тех же классов . Эти методы не должны содержать слова «alloc», «new», «copy» или «mutableCopy», которые, в соответствии с соглашением, указывают, что вызывающая сторона не владеет возвращаемым объектом, т.е. должны быть явно освобождены.

Связанные ресурсы:

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

Мета-ответ:

Один выпуск; этот метод должен быть объявлен как возвращающий идентификатор и должен return [[[self alloc] init] autorelease]; (одна или две строки, не имеет значения - просто следует обратиться к Класс напрямую). Как это, Фото Это будет боль для подкласса.

Расширение - учитывая это:

+ (Photo*) photo {
    Photo* newPhoto = [[Photo alloc] init];
    return [newPhoto autorelease];
}

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

Вместо этого сделайте следующее:

+ (id) photo {
    id newPhoto = [[self alloc] init];
    return [newPhoto autorelease];
}

Это исправляет обе проблемы:

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

  • , так как он возвращает id, вызывающие абоненты могут без проблем выполнить оба следующих действия:

    фото * р = [фото фото]; SubclassOfPhoto * s = [SubclassOfPhoto photo];

3 голосов
/ 15 июня 2011

В этом сценарии photo - это удобный метод, который возвращает вам autoreleased экземпляр класса.

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

Если вы знакомы с Factory Methods, метод photo аналогичен этому.

1 голос
/ 15 июня 2011

Как вы говорите, это эквивалентно статическому методу.В этом случае (и во всех случаях [ClassName className] методов) это в основном фабричный метод .Вы просите класс создать свой экземпляр и передать его обратно.Все такие методы должны возвращать автоматически освобожденный объект.

Вы можете спокойно игнорировать такие методы, если хотите - обычно будет эквивалент alloc + init, но часто более удобно использовать метод класса, особенно если вывы создаете объект throaway и не хотите его сохранять.

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

1 голос
/ 15 июня 2011

+photo как конструктор. Вам нужен способ получить объект для отправки методов экземпляра, и это дает вам автоматически выпущенный.

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

Может кто-нибудь объяснить мне причину, пожалуйста, почему автор выбрал метод (фото *) фото; объявить его как метод класса вместо метода экземпляра?

Это в основном оболочка конструктора литаний. Обратите внимание на источник:

+ (Photo*) photo {
    Photo* newPhoto = [[Photo alloc] init];
    return [newPhoto autorelease];
}

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

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