2016-05-31 104 views
1

我在School类具有可变mTeacher一个实例:分配一个实例变量本身

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

在实现文件中,我有方法- (Teacher *)getTeacher这应该返回任何现有的教师来说,如果有一个或创建一个并返回它:

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

可能有其他多个实例的方法调用此方法来获取Teacher实例&分配到mTeacher实例变量:

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

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

所以,如果分配的方法之一已经是Teacher一个实例mTeacher,呼吁[self getTeacher]当其他方法最终会与mTeacher = mTeacher下(因为- (Teacher *)getTeacher方法只是在这种情况下返回mTeacher) 。我的问题是,在Objective-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'方法初始化它呢?另外,你应该检查出[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]; 
    } 
    ... 
    } 

所以,如果mTeachernil那么只有它会叫getTeacher

在目标c中,您可以使用property。它会设置它的getter和setter方法。或者你需要这个对象在init方法中初始化一次。没有必要这样做。

1

它看起来像你想懒惰地实例化变量。

Objective-C中的常用模式是声明只读(非原子)属性并使用支持实例变量进行初始化。

@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 

编辑:如果不使用属性访问实例变量直接:

@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

这种方法没有错,为什么你不能在School init中创建Teacher对象。而且,如果您正在研究多线程环境,请确保您没有多次创建教师对象。

+0

你说得对,代码不是线程安全的。但是,在许多情况下仅使访问器是线程安全的是没有意义的。 (这就是为什么几乎没有人使用原子访问器。)但是,如果你想拥有线程安全性,现在应该使用GCD。 –

+0

我的意思是我们应该保护我们正在创建实例的地方(init方法),而不是访问者。 – Feroz

+1

@Feroz:惰性初始化非常有用,在许多情况下非常重要。 – 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 

此外,该代码不是线程安全的。