这是什么?糖果还是大蒜?
有关Objective-C的内容:
是否有任何问题不能在(+) - 类方法中使用'self'作为类?
在课堂深处...
+(NSDate*)dateWithTimeInterval:(NSTimeInterval)interval {
return [self dateWithTimeIntervalSince1970:interval];
}
Ruby在这里: 例如,在Ruby中,一切都是对象,而类是Class类的对象,并且有一个很好的实践可以依赖于self:
class DateClass
# self is DateClass here, inside of class definition, uh
self.dateWithTimeInterval(interval)
self.dateWithTimeIntervalSince1970(interval)
end
end
Perl: 在perl oop深度发现了另一个例子:(感谢this thread)
sub new {
my $proto = shift || die "Must pass a class or object into new()";
my $class = ref($proto) || $proto;
bless {}, $class;
}
所以,在Perl和Ruby中,人们总是依赖$class
refs
也许Perl代码的例子并不明显,但它始终发生。程序员依赖$ class引用并使用类名。他们也可以用它来调用一些方法:
my $class = 'Class';
$class->new();
或
Class::->new()
毕竟......
你可以提供哪些陷阱或警告反对使用self作为objective-c中的类?
答案 0 :(得分:1)
要了解使用self
与class name
的利弊,请考虑以下情况:
类A
是NSDate
的子类,并实现方法+(NSDate*)dateWithTimeInterval:(NSTimeInterval)interval
。
类B
是A
的子类,并覆盖+dateWithTimeIntervalSince1970:(NSTimeInterval)interval
中声明的NSDate
方法的实现。
现在让我们考虑+(NSDate*)dateWithTimeInterval:(NSTimeInterval)interval
中A
方法的两种可能实现:
1。使用self
+(NSDate*)dateWithTimeInterval:(NSTimeInterval)interval {
return [self dateWithTimeIntervalSince1970:interval];
}
如果运行[B dateWithTimeInterval:interval];
,则上面代码中的self
类似于B
类,并且B
方法的预期自定义实现(在类+(NSDate*)dateWithTimeIntervalSince1970:(NSTimeInterval)interval
中)将会被称为。
2。直接使用NSDate
+(NSDate*)dateWithTimeInterval:(NSTimeInterval)interval {
return [NSDate dateWithTimeIntervalSince1970:interval];
}
如果运行[B dateWithTimeInterval:interval];
,那么覆盖的实现(在类B
中)将被忽略而不是它:NSDate
方法的原始实现(在类+(NSDate*)dateWithTimeIntervalSince1970:(NSTimeInterval)interval
中)将是调用。这是因为我们直接向NSDate
发送消息:[NSDate dateWithTimeIntervalSince1970:interval];
对于开发人员来说,这种行
出于同样的原因,以这种方式声明方法:
+(instancetype)dateWithTimeInterval:(NSTimeInterval)interval {
return [self dateWithTimeIntervalSince1970:interval];
}
通过使用instancetype
编译器将知道method-initializer返回什么类型的对象。当您致电[B dateWithTimeInterval:interval]
时,它会返回实物B
但不是NSDate
的对象。
答案 1 :(得分:1)
通常情况下,只要可以使用self
,当然,有些情况下需要[MyClass class]
引用类。几乎所有场景都与继承有关。
例如,类A.
@implementation A
+ (id)createInstanceWithParam:(NSInteger)param {
return [[self alloc] initWithParam:param];
}
@end
即使我们创建了子类B
,它也能正常工作。但是,如果我们决定实现类集群,那么我们必须按名称引用类:
@implementation SomeDataStructure
+ (id)createInstanceWithType:(NSInteger)type {
if (type == 0) {
return [[DataStructureImpl1 alloc] init];
}
else if (type == 1) {
return [[DataStructureImpl2 alloc] init];
}
}
@end
另一个例子是+initialize
+ (void)initialize {
if (self == [MyClass class]) {
...perform initialization...
}
}
当然,如果要覆盖方法,那么使用self
或使用[MySelf class]
可以区分您的覆盖实现和原始实现。虽然super
也可以在那里使用。
TLDR:
self
是首选,但要小心子类/超类。