一起學Objective-C - 創建實現類(implementation)2

指定的初始化方法Designated Initializer

注意上篇文章例子中的initWithX:Y:方法,它被標記成爲制定的初始化方法。這個概念很重要,因爲它確保了類被合適的初始化了。這中指定的初始化方法應該是所有方法中控制最多屬性的,其他的初始化方法應該調用這個方法,或者調用其他初始化方法(但是最終還是調用這個方法)。

有指定初始化方法的好處是,一旦子類被創建,它只需要複寫指定初始化方法就夠了.如果沒有這麼做的話,外部代碼調用初始化方法的時候,只有父類的屬性被初始化好了,而子類的則沒有。正確的做法是,子類重寫這個指定的初始化方法,並調用父類的這個指定初始化方法。

@implementation SuperClass
- initWithA: (int)a
{
  return [self initWithA:a B:0];  // 0 is default value
}


// designated init for SuperClass
- initWithA: (int)a B: (int)b
{
  self = [super init];
  myA = a;
  myB = b;
  return self;
}
@end


@implementation SubClass


// overrides SuperClass's designated init
- initWithA: (int)a B: (int)b
{
  return [self initWithA: (int)a B: (int)b C: (int)c];
}


// designated init for SubClass
- initWithA: (int)a B: (int)b C: (int)c
{
  self = [super initWithA: a B: b];
  myC = c;
  return self;
}
@end

注意,上面的代碼中,"self"變量可以被重新定義,這和其他的OO語言不一樣。因此我們可以像這樣寫一個新的構造方法

{
  self = [[self alloc] init];
    // note "self" now refers to the new instance!
  [self setX: 1.0];
  return self;
}

另一點要注意的是Objective-C不強制要求必須首先調用父類的初始化方法。儘管上面的例子那樣做的但是那不是必須的 。如果需要的話,你可以在這之前做一些必要的事。

Objective-C中的單例


如果需要的話,有可能初始化方法返回一個已存在的對象而不返回新的對象。可以有幾種方法來實現這個。如果你在便捷構造函數中的話可以使用下面的方法

+ new
{
  if (singleton == nil)
    singleton = [[self alloc] init];
  return singleton;
}


如果你要在init裏實現的的話,就稍微複雜一些了。

- init
{
  if (singleton != nil)
    {
      RELEASE(self);
      self = RETAIN(singleton);
    }
    else
    {
      singleton = self;
    }
  return self;
}

這裏我們顯式的釋放了當前的實例,然後將它替換成已經存在的singleton。你在使用init方法的返回值時你永遠要多加小心。
id anObject = [SomeClass alloc];
  // this is bad:
[anObject init];
  // anObject might have been deallocated!
  // do this instead:
anObject = [anObject init];

上面的例子有問題,因爲有一種情況在使用GNUstep librar中的NSConnection時會實際發生,它只允許連接到已經存在的兩個端口,所以如果當已經連到一個端口以後你再調用initWithReceivePort:sendPort: ,這個方法會銷燬掉新allocate的實例,然後返回當前衝突的實例。

總的來說,最好是使用new而不是init方法來避免創建新的實例,然而因爲其他的一些設計約束,可能無法避免要使用init來做。

銷燬對象實例Instance Deallocation
- dealloc
{
  RELEASE(anInstanceVariableObject);
  NSZoneFree(NULL, myMemory);
  [super dealloc];
}

這裏我們使用了RELEASE宏,並且使用了NSZoneFree方法來釋放之前通過NSZoneMalloc或相關方法分配的內存. NULL表示內存是從默認的Zone分配來的.

最後我們調用了 [super dealloc], 在實現dealloc時應該總是這樣做,你不用管父類的dellocate,因爲它會自己管好自己的。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章