!!!Obj-C 2.0 -- Chapter 3 Allocating and Initializing Objects

3.1 Allocating and Initializing Objects

It takes two steps to create an object using Objective-C:

1. Dynamically allocate memory for the new object

2. Initialize the newly allocated memory to appropriate values

In objective-C, memory for new objects is allocated using class methods defined in the NSObject class. NSObject defines two methods:allocandallocWithZone:. They don't need to be overridden and modified in subclasses.

The alloc and allocaWithZone: methods initialize a newly allocated object's isa instance vairable so that it points to the object's class.All other instance variables are set to 0.

The initialization method begin with the abbreviation "init". If the method takes no arguments, the method name is justinit. If it takes arguments, labels for the arguments follow the "init" prefix. E.G.initWithFrame:

3.2 The Returned Object

An init... method normally initializes the instance variables of the receiver, then returns it.

If the init method cannot initialize a new object successfully, it may return nil, indicating the requested object can't be created. (e.g. file name is incorrect)

Because an init... method might return an object other than the newly allocated receiver, or even return nil, it's important that programs use the value returned by the initialization method, not just that returned byalloc or allocWithZone:

// bad implementation, ignore the return from nil
id anObject = [SomeClass alloc];
[anObject init];
[anObject someOtherMessage];
We should combine allocation and initialization messages in one line:

id anObject = [[SomeClass alloc] init];
[anObject someOtherMessage];
If init may return nil, we should check the return value before processing:

id anObject = [[SomeClass alloc] init];
if( anObject )
    [anObject someOtherMessage];
else
    ...

3.3 Implementing an Initializer

3.3.1 Constraints and Conventions

1. The name of a custom initializer method begins with init.

2. The return type of an initializer method should be id.

3. In the implementation of a custom initializer, you must invoke the superclass's designated initializer. By default, the designated initializer is init.

4. You should assign self to the value returned by the designated initializer.???

    when we do [anObject alloc], we will create a new instance. And all the self (whether in init method of anObject's class, or it's super class) will refer to the created instance. (self refer to the object that perform the method!)

5. If you set the value of an instance variable, you typically do so using direct assignment rather than using an accessor method.

6. At the end of the initializer, you must return self, unless the initializer fails in which case you return nil.

Example of custom initializer for a class inherited from NSObject and has a instance variable createDate:

- (id)init {
    // Assign self to value returned by super's designated initializer
    // Designated initializer for NSObject is init
    if (self = [super init]) {
        createDate = [[NSDate alloc] init];
    }
    return self;
}

3.3.2 Handling Initialization Failure

In general, if there is a problem during an initialization method, you should call [self release] and return nil.

Consequences of this policy:

1. Any object that receives a nil from an initializer method should be able to deal with it.

2. You must make sure that dealloc methods are safe in presence of partially-initialized objects.

Note: You should only call [self release] at the point of failure(we can only release the object once). If you get nil back from an invocation of the superclass's initializer, you should not also call release. This is typically handled by the pattern of performing initialization within a block dependent on a test of the return value of the superclass's initializer:

- (id) init {
    if (self = [super init]) {
        creationDate = [[NSDate alloc] init];
    }
    return self;
}
How to handle an inappropriate value passed as the parameter:

- (id)initWithImage: (NSImage *)anImage {
    if(anImage == nil) {
        [self release];
        return nil;
    }
    // else do the normal work
}

3.3.3 Coordinating Classes

The init... methods a class defines typically initializes only those variables declared in that class. Inherited instance variables are initialized by sending a message to super to perform an initialization method defined somewhere farther up the inheritance hierarchy.

The message to super chains together initialization methods in all inherited classes. Because it comes first, it ensures that superclass variables are initialized before those declared in subclasses.

E.G.

- (id)initWithName: (NSString *)string
{
    if( self = [super init] ) {
        name = [string copy];
    }
    return self;
}

A class must also make sure that all inherited initialization methods work. For example, if class A defines an init method and its subclass B defines an initWithName: method. B must also make sure that an init message successfully initializes B instances.

// init method implementation on B class
- init
(
    return [self initWithName:"default"];
)
The initWithName: method would invoke the inherited method, so initWithName is the designated initializer:


3.4 The Designated Initializer

The designated initializer is the method in each class that guarantees inherited instance variables are initialized(by sending a message to super to perform an inherited method).

It's important to know the designated initializer when defining a subclass.

Suppose we deinfe class C, a subclass of B, and implement an initWithName:fromFile: method. In addition to this method, we have to make sure that the inherited init andinitWithName: methods also work for instance of C. This can be done just by covering B's initWithName: with a version that invokesinitWithName:fromFile:

// initWithName: method defined in class C
- initWithName: (char *)string
{
    return [self initWithName:string fromFile:NULL];
}
We don't need to modify init method, as it's already modified in class B.
The designated initializer in a class must, through a message to super, invoke the designated initializer in a superclass.


B's init sends a message to self to invoke the initWithName: method. Therefore, when the instance is of Class B, it will invoke B's InitWithName: method; when the instance is of Class C, it will invoke C's InitWithName:

3.5 Combining Allocation and Initialization (left)

In cocoa, some classes defined creation methods that combine the two steps of allocating and initializing to return new, initialized instances of the class. These methods are often referred to asconvenience constructors.








  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值