2016-05-31 2 views
1

У меня есть экземпляр переменной mTeacher в моем School классе:Назначить переменную экземпляра к себе

@interface School : NSObject { 
    Teacher *mTeacher; 
} 
@end 

В файле реализации, у меня есть метод - (Teacher *)getTeacher который, как предполагается вернуть либо существующий экземпляр учителя, если есть один или создать и вернуть его:

- (Teacher *)getTeacher { 
    if (mTeacher != nil) { 
     return mTeacher; 
    } 
    return [[Teacher alloc] init]; 
} 

Там может быть несколько других методов экземпляра, вызывающие этот метод, чтобы получить Teacher экземпляр & присваиваемоеПеременнаяэкземпляра:

- (void)methodOne { 
    mTeacher = [self getTeacher]; 
    ... 
} 

- (void)methodTwo { 
    mTeacher = [self getTeacher]; 
    ... 
} 

Таким образом, если один из метода назначен уже экземпляр Teacher к mTeacher, другой метод при вызове [self getTeacher] бы в конечном итоге с mTeacher = mTeacher под (потому что - (Teacher *)getTeacher метод просто возвращает mTeacher в данном случае) , Мой вопрос в том, хорошо ли в объективе-C? Любые потенциальные проблемы с моим методом getTeacher?

+0

Вы внедряете шаблон дизайна Singleton. Вот еще один связанный пост по теме, который должен помочь: http://stackoverflow.com/questions/145154/what-should-my-objective-c-singleton-look-like –

+1

Я не вижу в этом ничего технически неправильно, но почему бы просто не инициализировать переменную один раз в методе 'init' и использовать ее там, где это необходимо, а не пытаться установить ее несколько раз? (В стиле: было бы больше соответствовать Objective-C, чтобы сделать «учителем» свойство, а не явную переменную. Затем, вместе с моим предложением о 'init',« getter »исчезнет из вашего кода.) –

+0

Если 'mTeacher' никогда не' nil', почему бы вам не инициализировать его в методе 'init'' School'? Кроме того, вы должны проверить это [Свойства в Objective-c] (https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html) – Sudo

ответ

0

Это хорошо с объективным c .. !! Вы не должны есть проблемы с этим я думаю, но вы можете проверить с, если - еще как,

- (void)methodOne { 

    if(!mTeacher){ 
    mTeacher = [self getTeacher]; 
    } 
    ... 
    } 

Так что, если mTeacher не nil только тогда он будет называется getTeacher.

В объективе c вы можете использовать property для этого. Он будет устанавливать методы getter и setter. Или вам нужен этот объект для инициализации один раз в методе init. не нужно так поступать.

1

Похоже, вы хотите, чтобы создать переменную лениво.

Обычный шаблон в Objective-C состоит в том, чтобы объявить свойство readonly (nonatomic) и использовать переменную экземпляра базы данных для инициализации.

@interface School : NSObject 

@property (readonly, strong, nonatomic) Teacher *mTeacher; 

@end 

@implementation School 
@synthesize mTeacher = _mTeacher; 

- (Teacher *)mTeacher { 
    if (!_mTeacher) { 
     _mTeacher = [[Teacher alloc] init]; 
    } 
    return _mTeacher; 
} 

@end 

Edit: Без использования доступа к свойству переменного экземпляра непосредственно:

@interface School : NSObject 
{ 
    Teacher *mTeacher; 
} 

@end 

@implementation School 

- (Teacher *)mTeacher { 
    if (!mTeacher) { 
    mTeacher = [[Teacher alloc] init]; 
    } 
    return mTeacher; 
} 

@end 

Однако, если вы хотите использовать явно сорбент, а не переменный экземпляр, вы должны написать

[self mTeacher]; 
+0

Мне было бы очень интересно знать версию, не используя '@ property' для ленивой инициализации, не могли бы вы показать мне это? –

+0

Я добавил пример для этого –

+0

@vadian. Ваш пример не будет компилироваться, потому что ivar не создается неявно, если вы перезаписываете все аксессоры. –

0

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

+0

Вы правы, что код не является потокобезопасным. Но использование во многих случаях исключительно аксессуаров в потоковом режиме бессмысленно. (Вот почему почти никто не использует атомарные аксессоры.) Однако, если вы хотите иметь безопасность потоков, в настоящее время следует использовать GCD. –

+0

Я имею в виду, что мы должны охранять место, где мы создаем экземпляр (метод init), а не аксессор. – Feroz

+1

@Feroz: ленивая инициализация _very_ полезна и во многих случаях существенна. – gnasher729

1

подход является правильным, но есть два замечания:

A. Вы никогда не можете быть «нет учителя» scheool, это означает, что свойство nil'd - для любой другой.

B. Очевидно, что вы начинаете с Objective-C из другого языка:

  • Не используйте m префикс для "членов". (Они не члены, а ивары.)

  • Не объявляйте ivars в интерфейсе.

  • Не используйте префикс get для геттеров.

Вы можете использовать свойство, как упомянуто vadian:

@interface School : NSObject 
@property (readonly, strong, nonatomic) Teacher *teacher; // without m 
- (Teacher*)teacher; // *Alternatively* without @property 
@end 

@implementation School 
// usually the ivar is created implicitly with the name _teacher. 
// However, you have a readonly property and overwrite all accessors 
// (in the case of a read only property there is only a getter) of the property, 
// no ivar will be created automatically. You have to do that explicitly. 
{ 
    Teacher *_teacher; 
} 

- (Teacher *)teacher { // no m 
    if (!_teacher) 
    { 
    _teacher = [[Teacher alloc] init]; 
    } 
    return _teacher; 
} 
@end 

Кроме того, этот код не поточно-безопасный.

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