Как правильно переопределить метод класса в Objective-C в подклассе?
во второй главе своей книги по программированию iOS Джо Конвей описывает использование "себя" в методах класса в случае подкласса. Я понимаю эту концепцию и имею вопрос о проблеме подклассов.
фон: мы создали класс владения, чей метод класса + randomPossession выглядит следующим образом:
+(id)randomPossession
{
NSArray *randomAdjectiveList = [NSArray arrayWithObjects:@"Fluffy", @"Rusty", @"Shiny", nil];
NSArray *randomNounList = [NSArray arrayWithObjects:@"Bear", @"Spork", @"Mac", nil];
unsigned long adjectiveIndex = rand() % [randomAdjectiveList count];
unsigned long nounIndex = rand() % [randomNounList count];
NSString *randomName = [NSString stringWithFormat:@"%@ %@", [randomAdjectiveList objectAtIndex:adjectiveIndex], [randomNounList objectAtIndex:nounIndex]];
int randomValue = rand() % 100;
NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c",
'0' + rand() % 10,
'A' + rand() % 10,
'0' + rand() % 10,
'A' + rand() % 10,
'0' + rand() % 10];
Possession *newPossession = [[self alloc] initWithPossessionName:randomName valueInDollars:randomValue serialNumber:randomSerialNumber];
return [newPossession autorelease];
}
Я знаю, что возвращаемое значение действительно должно иметь тип id, такой что id newPossession = ...
Я подкласс владения и создал класс BallGlove, который включал новый iVar, brandName, NSString*
Я преодолел + randomPossession в BallGlove следующим образом:
+(id)randomPossession
{
BallGlove *myGlove = [super randomPossession];
NSArray *brandNames = [NSArray arrayWithObjects:@"Rawlings", @"Mizuno", @"Wilson", nil];
unsigned long randomNameIndex = rand() % [brandNames count];
[myGlove setBrandName:[brandNames objectAtIndex:randomNameIndex]];
NSLog(@"myGlove is of type class: %@", [self class]);
return myGlove;
}
мой вопрос таков: является ли способ, которым я преодолел этот метод класса, подходящим и приемлемым сообществом (т. е. параллельным формату-init, захватив супер-реализацию в переменной, соответственно манипулируйте переменной, а затем верните ее? Мой вывод показывает, что возвращаемый объект имеет пример BallGlove однако, я был заинтересован в приемлемой реализации. Спасибо заранее.
4 ответов
технически все в порядке.
Я бы предложил альтернативу. Если у вас уже есть назначенный открытый инициализатор в базовом классе (который вы можете создать и вызвать из этого метода класса фабрики в любом случае), а затем использовать этот самый инициализатор (или даже новый из вашего подкласса) в методе класса подклассов.
Это не намного больше кода, но на мой взгляд легче следовать и в будущем. Инициализатор может пригодиться также в какой-то момент, но конечно это не решение для каждого приложения.
Да, это вполне разумный способ сделать это. Между методами класса и обычными методами нет ничего особенного - только то, что один выполняется классом, а другой-экземпляром.
в тот момент, когда вы переопределяете метод класса, вы можете решить реализовать его с помощью супер-реализации или без нее. Это полностью зависит от вас. Overiding init-это совершенно другая история, не только потому, что это метод экземпляра, но и потому, что он связан с Конвенцией/договором. Имейте в виду, что, например, не следует нарушать принцип подстановки Лискова.
ваш переопределенный метод класса отлично подходит, хотя я бы рассмотрим методы класса overiding как запах дизайна. Хотя это очень хорошо возможно в Objective-C, это не на других языках, и это по очень веской причине. Полиморфизм как понятие лучше привязан к экземплярам, которые могут использоваться в качестве заменителей друг друга, тогда как использование методов класса нарушает понятие (т. е. нет реальной подстановки). Это умно, но не necessesarily интуитивно понятный и гибкий.
Да, это приемлемо, чтобы сделать вашу инициализацию, как это. На самом деле именно так это и делается в большинстве случаев. Я имею в виду, что это причина для наследования от супер класса в первую очередь. Вы хотите в дополнение к тому, что присутствует в супер класс. Таким образом, вы вставляете код в то, что специфично для унаследованного класса, и это должно быть сделано таким образом.
Я думаю, как вы хотите BallGlove
инициализированный объект также является фактором в определении унаследованного метода. Этот вопрос возникает при вызове Possession
init или вызов BallGlove
инит (не создавая экземпляр класса, чтобы использовать метод класса). Таким образом, это сводится к логике создания ваших объектов, т. е. как вы хорошо описываете BallGlove
object - вы убедитесь, что ваш метод класса описывает его таким образом, который соответствует BallGlove
критерии объекта и не становится общим