Создание класса без init метода (Цель-c)

Действительно ли возможно создать класс без init метода, чтобы вынудить все вызывающие стороны создать объект с методом фабрики вместо этого?

8
задан Casebash 2 February 2010 в 23:24
поделиться

5 ответов

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

Так как вы унаследовали от NSObject, у вас есть метод init и нет ничего, что вы не можете сделать, чтобы предотвратить его называться. Тем не менее, вы могли бы переопределить init к этому:

- (id)init
{
   [self dealloc];
   @throw [NSException exceptionWithName:@"MyExceptionName" reason:@"Reason" userInfo:nil];
   return nil;
}

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

5
ответ дан 5 December 2019 в 17:37
поделиться

Если вы действительно хотели создать проблемы для пользователей вашего класса, которые используют init , вы можете сделать:

@implementation MyClass

- (id) init
{
    // Still have to make sure the runtime has initialised everything for "self"
    self = [super init];
    if (!self) return nil;
    [self release]; // some say you should use [super dealloc]
    [super doesNotRecognizeSelector:_cmd];
    return nil;
}

@end

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

4
ответ дан 5 December 2019 в 17:37
поделиться

NSObject реализует для вас метод init , который делает то, что делает. Если вашему классу нечего настраивать при его создании, просто не переопределяйте метод - (id) init , предоставленный NSObject . Но вы все равно вызываете его при создании экземпляра.

0
ответ дан 5 December 2019 в 17:37
поделиться

Зависит от ситуации. Если ваш класс наследуется от NSObject, он будет иметь унаследованный метод init (который ничего не делает с переменными экземпляра). Так что в этом смысле, даже если бы вы очень хотели не иметь метода init, он у вас, скорее всего, все равно будет. Так что если ваш вопрос был "Нужно ли мне реализовывать тривиальный метод init?", то ответ будет "нет, не нужно". Однако если ваш вопрос был "Нужно ли мне вызывать метод init, если я его не переопределил?", то ответ будет "да, нужно". Что бы вы ни делали с подклассами NSObject, в какой-то момент вам все равно придется вызвать init после создания объекта. Такова жизнь.

Учитывая это, вам скорее всего нужен метод init, если только инициализация вашего объекта не требует ничего, кроме обнуления всего объекта.

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

1
ответ дан 5 December 2019 в 17:37
поделиться
>>> [m.groupdict() for m in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

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

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

-121--4518441-

Самое близкое, что я могу получить:

>>> [match.groupdict() for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk')]
[{'i': None, 'b': 'abc'}, {'i': 'hij', 'b': None}]

Как вы объединяете словари, то зависит от того, ожидаете ли вы более одного совпадения. Если требуется только одно совпадение, можно выполнить:

>>> results = {}
>>> for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijk'):
...     results.update(dict((k,v) for k, v in match.groupdict().iteritems() if v is not None))
... 
>>> results
{'i': 'hij', 'b': 'abc'}

Или для нескольких совпадений:

>>> results = defaultdict(lambda: [])
>>> for match in re.finditer('(?P<b>.b.)|(?P<i>.i.)', 'abcdefghijkabcdefghijk'):
...     for k, v in match.groupdict().iteritems():
...         if v is not None:
...             results[k].append(v)
... 
>>> results
defaultdict(<function <lambda> at 0x7f53d0992c08>, {'i': ['hij', 'hij'], 'b': ['abc', 'abc']})
-121--4518442-

Конечно. В Objective-C отсутствуют фактические конструкторы . init - методы типа обычно используются для инициализации класса в том же ключе, что и конструктор, но они являются просто «нормальным» методом (в них нет ничего особенного, как в конструкторах Java).

Это означает, что, если класс не инициализирует без для своих экземпляров, вы, вероятно, хотите, чтобы имел какой-то метод init .

0
ответ дан 5 December 2019 в 17:37
поделиться
Другие вопросы по тегам:

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