Nano Hash - криптовалюты, майнинг, программирование

Цель C: Объяснение метода класса

В процессе перехода с C++ на Objective-C я интенсивно читал книгу Cocoa и Objective C запущены и работают.

В одном из примеров кода книги есть строка, которая не имеет для меня смысла с моим нынешним уровнем знаний:

Это объявление метода класса + (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
14.06.2011

  • Что интересно, это объявление метода неверно. Все инициализаторы должны возвращать id, а конструкторы должны использовать self (что относится к классу внутри метода класса), а не жестко запрограммированное имя класса. Эти две вещи необходимы для правильной работы подклассов. РЕДАКТИРОВАТЬ: я вижу, что bbum уже упоминал об этом ниже, но я думаю, что стоит повторить. 15.06.2011
  • @ Джош Точно; расширен в мета-ответе ниже. 15.06.2011

Ответы:


1

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

По сути, это оболочка конструктора. Обратите внимание на источник:

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

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

14.06.2011
  • +1, привет Майк. Отлично объяснил. Спасибо. Итак, если я правильно понимаю, это один из очень немногих случаев, когда идентификатор метода объявлен как метод класса, а не как метод экземпляра. 15.06.2011
  • Несмотря на то, что все ответы были правильными, я думаю, что этот объяснил мой вопрос самым ясным образом. Поскольку я могу выбрать только один ответ как Принятый ответ, я хотел бы отметить его. 15.06.2011
  • Один выпуск; этот метод должен быть объявлен как возвращающий id и должен return [[[self alloc] init] autorelease]; (одна строка или две, не имеет значения - просто следует напрямую ссылаться на класс). Как бы то ни было, Photo будет проблемой для подкласса. 15.06.2011
  • @bbum: Пожалуйста, уточните, что Photo будет проблемой для подкласса. Я новичок в Obj-C и хотел бы получить некоторое представление. 15.06.2011

  • 2

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

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

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

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

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

    14.06.2011

    3

    Мета ответ:

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

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

    + (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, вызывающие могут без проблем выполнять оба следующих действия:

      Фото *p = [Фото фото]; SubclassOfPhoto *s = [SubclassOfPhoto photo];

    15.06.2011
  • Таким образом, photo становится настоящим фабричным методом, поскольку подклассам не нужно определять свои собственные версии. 16.06.2011
  • Точно; как бы то ни было, это фабрика, жестко привязанная к определенному классу. Не так хорошо для кластеров классов и других подобных шаблонов. 16.06.2011

  • 4

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

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

    Если вы знакомы с фабричными методами, метод фотографий аналогичен этому.

    14.06.2011
  • +1 -Привет, Майкл. Отлично объяснил с вашей стороны и понял с моей. Спасибо. 15.06.2011

  • 5

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

    14.06.2011
  • +1, привет, Джереми, спасибо за ответ. Что произойдет, если я объявлю метод как метод экземпляра? Могу ли я создавать объекты с его помощью, пожалуйста? 15.06.2011
  • Нет, потому что у вас возникла бы проблема с курицей и яйцом: как получить экземпляр объекта для отправки метода экземпляра? В этом случае ваш метод экземпляра -photo будет больше похож на -copy или -clone по духу, чем на конструктор. 15.06.2011
  • Теперь я понимаю. Спасибо, Джереми. 15.06.2011

  • 6

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

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

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

    14.06.2011
  • Кластер классов прекрасно справляется со стандартным танцем alloc-init. Просто -init почти наверняка вернет объект, отличный от -alloc. См., например, NSString или NSArray, где alloc-init прекрасно работает для создания нового экземпляра. 15.06.2011
  • +1 -Привет, Том, и спасибо за объяснение. Вы даже предоставили немного больше полезной информации. Я понял, что ты сказал. 15.06.2011
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

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

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

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..