【问题标题】:Object Makeup, how its constructed?对象化妆,它是如何构造的?
【发布时间】:2010-12-01 02:11:42
【问题描述】:
这些都是相当简单的问题,但在继续之前我想先弄清楚一些事情......
@interface BasicTire : NSObject {
}
@end
@interface SnowTire : BasicTire {
}
@end
当您调用 [SnowTire init] 时,包含的 [super init] 会调用 [BasicTire init],而后者又会调用 [NSObject init]? (即运行到父/超类的级联。
当您 [SnowTire 分配] 时,您正在创建一个新对象,其中包括其超类的功能。我是否认为您没有创建以某种方式链接的多个对象(即 SnowTire > BasicTire > NSObject)。
只是想检查一下...
加里
【问题讨论】:
标签:
objective-c
cocoa
cocoa-touch
【解决方案1】:
是的,通常初始化程序调用超类初始化程序。这是在 init 方法的实现中明确完成的。虽然可以调用同一类或其超类的其他初始化程序,但有必要确保始终调用 "designated initializer"。
如果一个对象没有实现init(或有问题的初始化程序),则调用超类中的那个(与任何其他方法一样)。这并不罕见,因为在 Objectve-C 中实例变量总是初始化为零(在 alloc 中),因此通常不需要实现专门的 init。
alloc 只是分配内存并设置确定对象类的对象的“isa 指针”。你从中得到的是一个未初始化的对象(不是链表),它为所有实例变量(包括超类)留有空间。
【解决方案2】:
是的。每个初始化器都必须为超类调用指定的初始化器,一直到NSObject。同样重要的是,每个初始化器都将超级初始化器的结果分配给自身。因为不需要初始化器返回您发送初始化消息的同一实例。
是的。 alloc 在堆上为对象实例变量初始化了足够的内存,并用零清除此内存。这样所有的指针都会是nil、布尔值false等。然后它将isa指针设置为新对象的类。
【解决方案3】:
当您调用 [SnowTire init] 时,包含的 [super init] 会调用 [BasicTire init],而后者又会调用 [NSObject init]? (即运行到父/超类的级联。
您同时实现了-[SnowTire init] 和-[BasicTire init],因此您只需查看您的实现即可看到:
- 您的
-[SnowTire init] 使用[super init] 调用-[BasicTire init]。
- 您的
-[BasicTire init] 使用[super init] 呼叫-[NSObject init]。
[super init] 总是调用下一个可用的实现,即使它不在您的直接超类中。如果不实现-[BasicTire init],那么-[SnowTire init] 中的[super init] 表达式将调用-[NSObject init]。这很好,因为您显然认为 BasicTire 不需要任何初始化。 (如果是这样,那么您遗漏了-[BasicTire init] 是一个错误。)
当您 [SnowTire alloc] 时,您正在创建一个新对象,其中包括其超类的功能。我是否认为您没有创建以某种方式链接的多个对象(即 SnowTire > BasicTire > NSObject)。
是的。每个对象都有一个类(在名为isa 的变量中,如“这个实例是一个 SnowTire”),每个类都有一个超类和一个元类。 -alloc 和 -init 与所有 Objective-C 方法和 C 函数一样,都只返回一个东西——在这种情况下,一个实例对应一个类。
因此,例如,当您向雪地轮胎发送gripTheSnow 消息时,它会使用 SnowTire 对该方法的实现。如果你发送一个retain 消息,那么你没有在SnowTire 中实现retain,你也没有在BasicTire 中实现它,所以它使用了NSObject 的实现。运行时搜索,从对象的类(在本例中为 SnowTire)开始,沿着类层次结构的直线向上搜索,到诸如 NSObject 之类的根类结束。