今天在学习Objective-C时见到某初始化函数中有如下代码:
self = [super init];
if(self){
// Initialize members
}
return self;
当时只是觉得Objective-C与才C++应该一样,每个子类对象都包含父类对象,所以super与self都是指向同一对象的头部的,[super
init]返回的地址应该与self所代表的地址一样(即self == [super init])。那么,对self赋[super
init]的值岂不是没有什么意义?
找朱去讨论,他也不知道是因为什么。但是他想起了在《From C++ to Objective-C》中好像提到过这个情况,于是在一通查找之后终于在7.1.3(P25)找到了说明。那一节的例子中的对应代码是这样的:
if(![super init])
return nil;
// Initialize members
return self;
同时下面又相应的说明:
Polemic: Most people use the instruction self = [super init]; if (self)
{...} in the initializer. This is justified by the fact that in some
cases, [super init] could return a different object. However, in a very
interesting document [6], Will Shipley shows that is a bad practice. It
is far more logical to use the above form, where it is only checked
whether [super init] returns nil or not.
意思是很多人采用了self =
[super init]; if (self) {...}的方法,这是由于有一些实践已经证明了[super
init]有可能返回一个(与self所指对象)完全不同的对象。但作者推荐了一篇文章,说这篇文章证实了这个为大多数人所使用的初始化方式是一种不好的
手法。
这里所说的 a very interesting document[6] 指的是:
[6] Will Shipley. self = [supid init]. http://wilshipley.com/blog/2005/07/
self-stupid-init.html.
是一篇博文。在这篇博文里,作者对比了两种形式的初始化方法,它们是:
1.Traditional -init
- (id)init;
{
if ((self = [super init]) == nil)
return nil;
[...initialize my stuff...]
return self;
}
2.Wil's -init
- (id)init;
{
if (![super init])
return nil;
[...initialize my stuff...]
return self;
}
作者认为不可能存在不用self = [super init]就不对的情况,所以他认为第二种方法才是正确的。他曾在以前的一篇博文上说谁能找到这样的情况就给那人20美元。
但现在作者坦言这样的情况确实存在——一个名叫Ken
Ferry的人编写了一个程序,该程序会自动为Cocoa库的每一个类派生出子类并产生程序将其实例化,并在初始化时判断[super
init]是否返回的就是self。最终该程序Ken Ferry终于找到了一些这样的类——它们都是 single intance(单实例)的类。
说到这里大家想必也都知道是怎么回事了,单实例的类初始化函数在第一次被调用时会返回新的实例,以后再被调用则只会返回第一次生成的实例。在这种情况下,
作者提出的方式2也就有了问题 ——若遇到父类采用单例模式,则在子类中[super
init]返回的确实非nil,但却也不再是子类对象所包含的那个父类对象了。如此一来子类对象所包含的那个父类对象并未被初始化,没有达到初始化函数的
目的。
但是我们也应该注意到第一种方式也是不对的——self被重新定向为指向父类那个单实例,如此一来则发生了内存泄露,因为self原先所指向的对象变成了“没有链子栓着的狗”(没有指针指向它)。
原来两种方式都存在不足,那么该如何是好呢?作者提出了第三种方式:
id superInitReturn = [super init];
if(!superInitReturn || self != superInitReturn)
{
return nil;
}
// Initialize memebers
return self;
我个人对此方法的理解是:若[super
init]返回的与self不同,则说明父类是单实例类,而单实例类的init函数应该是被重写过的,一般会返回nil,遇到这种情况我们就该收手了——
让你的类去继承一个单实例类并非好的设计(如果想达到类似效果,请让这个单实例成为你的类的成员)——故而返回nil。
值得一提的是该博文为作者2005年所作,作者于2009年在末尾追加了更新,指出苹果公司有些说明表明了他们很有可能要重写[NSObject init]方法,主要是因为要采用新的内存管理手段以提高内存重用率,所以作者最终推荐的init方式为:
-(id) init
{
if(!(self = [super init]))
{
return nil;
}
// Initialize members
return self;
}
原文如下:
Update April, 2009:
There's
been hints from Apple that they might modify the standard -[NSObject
init] method to try to re-use old object's memory, since it turns out
that a very common usage pattern is for programs to keep creating and
deallocating, say, 12 objects of the same class, over and over. Re-using
the exact same memory ends up being a big win (and this is a trick the
iPhone already does with its UITableViewCell class, and that is a HUGE
win if you do it yourself on the iPhone).
So, from now on, I recommend everyone uses:
Subclassing NSColorPanel the Right Way
- (id)init;
{
if (!(self = [super init]))
return nil;
// other stuff
return self;
}
I do.
我还是感到不解,看不出他的理由是什么。明天继续研究,也希望有高手能来指点一二。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/Cheng_Tian/archive/2010/07/16/5740831.aspx
分享到:
相关推荐
Objective-C是C语言的超集,它扩展了C语言,加入了面向对象的特性。面向对象编程(OOP)的核心概念包括类、对象、继承、封装和多态。Objective-C通过消息传递机制实现了这些概念,使得代码更加模块化和可维护。 2....
Objective-C中的`NSLog`函数用于输出调试信息,常用于查看程序运行时的状态或调试信息。 ```objective-c NSLog(@"Hello, World!"); ``` ##### 2.6 控制结构 Objective-C中的控制结构与C语言基本一致,包括但不...
方法(Methods)是Objective-C中执行特定任务的函数。它们可以分为实例方法(针对特定对象)和类方法(针对整个类)。方法的声明通常包含一个返回类型和一组参数,使用“-”表示实例方法,“+”表示类方法。方法名...
在Objective-C中,对象通过发送`alloc`消息(即调用`malloc()`或等价函数)进行分配,而初始化则通过调用`init`方法完成。 类在Objective-C中扮演着对象工厂的角色。大部分类不需自己实现`+alloc`方法,而是从其父...
在Objective-C中,函数调用实际上是一种消息发送机制。例如: ```objective-c Person *person = [[Person alloc] init]; person.name = @"John Doe"; [person speak]; ``` 这里,`[[Person alloc] init]`创建了一...
Block是Objective-C中的匿名函数,可以捕获和存储其所在作用域内的变量。它们在处理回调、排序或过滤数组等任务时非常有用。 Foundation框架是Objective-C的基础,包含了大量常用的数据类型和工具,如NSArray、...
`NSLog`是Objective-C中的日志输出函数,类似于C语言的`printf`。它支持多种格式化输出,例如`%@`用于输出对象,`%d`或`%i`用于输出有符号整数,`%u`用于输出无符号整数,`%f`用于输出浮点数,`%p`用于输出指针地址...
在Objective-C中,对象是通过创建类的实例来实现的,使用`init`方法初始化。 2. **类**:类是对象的蓝图,定义了一组共享的属性和方法。在Objective-C中,类使用`@interface`关键字声明,`@implementation`关键字...
Swift支持使用`lazy`属性修饰符来实现延迟初始化,类似于Objective-C中的懒加载属性。 **错误报告** Swift使用错误处理机制来处理异常情况,而Objective-C则使用`NSError`对象。Swift提供了与Objective-C错误报告...
Block是Objective-C中的一种闭包实现,它可以捕获和存储其所在上下文中的局部变量。Block常用于异步操作,回调函数,或者作为参数传递。 7. **内存管理**: 在Objective-C中,内存管理主要依赖于ARC(Automatic ...
- **构造函数**:Objective-C 中的构造函数通常通过 `- (instancetype)init` 方法来实现。 - **访问控制**:虽然 Objective-C 不像 Java 那样有严格的访问修饰符,但可以通过约定来控制成员的可见性。 - **继承与...
在Objective-C中,通常将函数称为“方法”,并且它们被定义在类中。例如: ```objective-c // 函数声明 - (void)printHello; // 函数实现 - (void)printHello { NSLog(@"Hello, World!"); } ``` #### 三、面向...
1. Block:Objective-C支持块(Block),一种内联函数,可以捕获并存储其所在作用域的变量。常用于异步编程。 2. GCD(Grand Central Dispatch):苹果提供的多线程解决方案,使用Block简化并发编程。 七、...
Objective-C 2.0 是苹果公司开发的一种面向对象的编程语言,它是C语言的超集,主要用于iOS和macOS的应用程序开发。Objective-C 2.0在Objective-C的基础上添加了一些新特性,使得代码更加简洁易读,提高了开发效率。...
在Objective-C中,我们使用`alloc`和`init`方法来创建对象。例如,`NSObject *obj = [[NSObject alloc] init];`。`alloc`分配内存,`init`初始化对象。 3. **类和对象**: 类是对象的模板,定义了对象的属性...
在iOS开发中,Objective-C是一种常用的编程语言,它在实现对象间的通信时有着独特的机制。本文将深入探讨如何利用Objective...通过阅读和理解这个示例,你应该能够更好地掌握Objective-C中利用协议实现回调函数的技术。
### Objective-C编程语言 #### 简介 Objective-C是一种简单但功能强大的...Objective-C作为一种面向对象的语言,在iOS开发中扮演着至关重要的角色,理解这些核心概念对于成为一名高效的Objective-C开发者至关重要。
嵌套方法调用在Objective-C中也很常见,它允许将一个函数调用的结果作为参数传递给另一个函数。为了避免降低代码可读性,应当尽量避免多层嵌套。 Objective-C允许一个方法可以有多个输入参数,参数之间通过冒号分隔...
Objective-C中的对象交互是通过消息传递的方式实现的,而非传统的函数调用方式。这意味着当你调用一个对象的方法时,实际上是向该对象发送了一个消息,请求执行某个操作。这种方式更接近于真实世界的交互模型,也为...