Ios 将实例变量分配给自身
在我的Ios 将实例变量分配给自身,ios,objective-c,Ios,Objective C,在我的学校班级中,我有一个实例变量mTeacher: @interface School : NSObject { Teacher *mTeacher; } @end 在实现文件中,我有一个方法-(Teacher*)getTeacher,它应该返回现有的教师实例(如果有),或者创建一个并返回它: - (Teacher *)getTeacher { if (mTeacher != nil) { return mTeacher; } return
学校
班级中,我有一个实例变量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
方法有任何潜在问题吗?目标c没有问题。。!!我想你不应该对这件事有异议,但你可以问一下,如果不是这样的话
- (void)methodOne {
if(!mTeacher){
mTeacher = [self getTeacher];
}
...
}
因此,如果mTeacher
不是nil
,那么只有它会被调用getTeacher
在目标c中,您可以为此使用
属性。它将设置它的getter和setter方法。或者需要在init方法中初始化此对象一次。不需要这样做。看起来您希望延迟实例化变量
Objective-C中的常见模式是声明一个只读(非原子)属性,并使用backing实例变量进行初始化
@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
但是,如果要显式使用getter而不是实例变量,则必须编写
[self mTeacher];
这种方法没有错,为什么不能在学校初始化中创建教师对象呢。此外,如果您在多线程环境中工作,请确保您没有多次创建教师对象。方法是正确的,但有两点需要注意:
答:你永远不会有一个“没有老师”的scheool,这意味着财产为零——不管是什么
B.显然,你从另一种语言的Objective-C开始:
- 不要使用
m
前缀作为“成员”。(他们不是成员,而是IVAR。)
- 不要在接口中声明IVAR
- 不要为getter使用
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
此外,此代码不是线程安全的 您正在实现单例设计模式。下面是关于这个主题的另一篇相关文章,应该会有所帮助:我看不出它在技术上有什么问题,但是为什么不在init
方法中初始化变量一次,并在需要的地方使用它,而不是尝试多次设置它呢?(关于风格:将teacher
设置为属性而不是显式变量更符合Objective-C。然后,随着我关于init
的建议,“getter”将从您的代码中消失。)如果mTeacher
从不nil,为什么不在School
的init
方法中初始化它呢?另外,你应该看看这个,我很想知道不使用@property
进行延迟初始化的版本,你能给我看看吗?我添加了一个示例that@vadian如果覆盖所有访问器,您的示例将无法编译,因为ivar不是隐式创建的。@Aminegm Awad,谢谢,我更喜欢合成。但是,你必须明确地这样做,就像你在编辑中所做的那样。你是对的,代码不是线程安全的。但是,在许多情况下,仅使访问器线程安全是毫无意义的。(这就是几乎没有人使用原子访问器的原因。)然而,如果你想实现线程安全性,现在就应该使用GCD。我的意思是我们应该在创建实例的地方(init方法),而不是访问器来保护线程。@Feroz:惰性初始化非常有用,在很多情况下是必要的。@gnasher729:同意。我不否认这一点,我只是告诉你,在创建实例时要确保线程安全,这句话有什么不对吗?