2012-04-15 4 views
0

Это может быть глупый вопрос, но здесь все равно. В объекте c, в методе инициации дочернего класса часто задается self = [super init]. Теперь я имеет дочерний класс, и преобразование не требуется, что означает (или нет ..), что метод init родительского класса каким-то образом возвращает объект, который действительно принадлежит дочернему классу.Метод/свойство в родительском классе, возвращающем объект из дочернего класса

Итак, мой вопрос: могу ли я определить другие методы или свойства в родительском классе, который при вызове из дочернего класса возвращает объект из дочернего класса? Существует что-то подобное в Java называется фабричные методы, я думаю, так что, возможно, этот вопрос не слишком возмутительно ..

Edit 1. Позвольте мне лучше объяснить, что я имею в виду: я знаю, что я могу узнать в методе ParentClass , что я фактически работаю над объектом из класса ChildClass. Это, глядя на [self class]. Тем не менее, я хотел бы объявить метод в ParentClass, что возвращает объект из дочернего класса, не зная, какой класс будет дочерним. Еще лучше, я хочу, чтобы возвращаемый объект даже не нуждался в формальном преобразовании.

Например, я хочу метод в родительском классе, что делает что-то вроде следующего:

-(ChildClass *) partialCopyOfSelf { 
//returns an object which is a partial copy of self (only copying properties that also 
// exist in parent class, but such that applying [result class] will yield the child class 
// and will require no further conversion 

(ChildClass *) copy=[[ChildClass alloc] init]; 
//now copy stuff 
return copy; 
} 

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

-(MyClass *) copyOfSelf { 
MyClass *copy=[super partialCopyOfSelf]; 
// now copy properties that only exist in my child class 
return copy; 
} 

Редактировать 2 (из комментария, который я написал в @wbyoung). Причина, по которой я хочу, это то, что в какой-то момент я могу изменить свойства родительского класса из ivars, возможно, просто вычислив некоторые значения, например, чтобы ребенок не знал, как правильно их скопировать. Я пишу это, потому что у кого-то есть лучшее представление о том, как выполнить ту же задачу.

ответ

2

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

При этом вы можете переопределить методы в своем дочернем классе.Сообщения всегда отправляются объекту & Поиск метода начинается с самого верхнего класса.

Вы также можете сделать что-то вроде [self class], чтобы выяснить свой тип в родительском классе. Тем не менее, это пока доставит вас. [[self class] displayColor] позволит вам сделать что-то вроде реализации метода & по умолчанию метода класса класса в базовом классе, но при необходимости переопределить метод класса в подклассах.

+0

см. Мое редактирование и мой комментарий для ответа @ Jenox – user1258240

+0

Re: ваше редактирование. Это просто похоже на плохую идею. Вы можете вызвать '[[[self class] alloc] init]', чтобы сделать копию (или даже пропустить 'init'), после чего оценивая значения по мере необходимости, но использование частичной копии похоже на то, что у вас возникнут проблемы. – wbyoung

+0

Да, я думаю, я мог бы это сделать, спасибо! Что касается беды - я чувствую себя достаточно предприимчивым, чтобы попробовать в любом случае, но был бы рад, если бы вы могли указать сценарий, когда этот подход был бы хлопотным. Причина, по которой я хочу, это то, что в какой-то момент я могу изменить свойства родительского класса из ivars, возможно, просто вычислив некоторые значения, например, чтобы ребенок не знал, как правильно их копировать. – user1258240

0

Да. Obj-C подчиняется всем правилам подкласса, которые вы найдете на большинстве языков OO.

Например ..

@interface Foo : NSObject 

@property (readonly) BOOL thing1; 
@property (readonly) CGFloat width; 

@end 

@implementation Foo 

-(BOOL)thing1 
{ 
return YES; 
} 

-(CGFloat)width 
{ 
return 30.0f; 
} 

@end 

Интерфейс Bar не требует заявлений или реализации thing1 или width.

@interface Bar : Foo 

@end 

@implementation Bar 

-(BOOL)thing1 
{ 
if(test) return YES; 
else return NO; 
} 

-(CGFloat)width 
{ 
return [super width] + 20.0f; 
} 

@end 

Однако вы можете реализовать thing1 и/или width в подклассе, чтобы обеспечить различные значения.

Экземпляры родительского класса всегда возвращают YES для свойства thing1, в то время как его панель подкласса может возвращать ДА или НЕТ в зависимости от результата теста (например).

Другое свойство width использует значение родительского класса и изменяет его.

0

Это может быть глупый вопрос, но здесь все равно. В объекте c, в методе инициирования дочернего класса часто задается self = [super init]. Теперь self является дочерним классом, и не требуется преобразование , что означает (или нет ..), что метод init родительского класса каким-то образом возвращает объект, который фактически принадлежит дочернему классу .

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


Так что мой вопрос: могу ли я определить другие методы или свойства в родительского класса, когда вызывается из дочернего класса возвращает объект из класса ребенка? Существует что-то подобное в Java называется фабричных методов, я думаю, так что, возможно, этот вопрос не слишком возмутительно ..

При возврате self в реализации суперкласса, то вы получите обратно тот же объект, как метод вызывается. Таким образом, ответ был бы да.

+0

Пожалуйста, см. Мое новое редактирование с лучшим объяснением того, что я имел в виду. Поэтому, исходя из вашего ответа, я могу просто вернуть тип id в свой метод partialCopy и назначить его (MyClass *) в дочернем классе? Думаю, он должен работать, хотя он менее безопасен, чем хотелось бы с точки зрения ловли ошибки .. – user1258240

Смежные вопросы