2010-05-19 25 views
1

下面的代碼是僞代碼。 想象一下有一個類「水果」,它有一種工廠方法來創造水果。Objective-C基礎知識:子類和成員變量可訪問性

interface Fruit 
{ 
} 
+(Fruit*) createFruit: 
{ 
    return [[Fruit alloc] init autorelease]; 
} 

現在我想子類的水果,以獲得一個蘋果:

interface Apple : Fruit 
{ 
int iSeeds; 
} 
+(Apple*) createAppleWithColor: (int) iSeeds 
{ 
Apple* oApple = [Apple createFruit:]; 
oApple.iSeeds = iSeeds; 
return oApple; 
} 

問題:

  • 我怎樣才能讓「iSeeds」不公開,不能從外部改變?如果我添加「私人」關鍵字,它不會再生成。
  • 我仍然想從蘋果的工廠方法中設置iSeeds。
  • 我希望用戶允許讀取iSeeds的內容。所以我想我應該有一個吸氣劑,但我不能讓它工作。我總是會得到一些關於「LValue任務」的錯誤。
  • Fruit的createFruit正在使用autorelease。蘋果是否必須重新放置/釋放任何東西?

回答

1

一對夫婦的事情。

  1. 您的createFruit方法是錯誤的。它應該是:

    + (Fruit *) createFruit { 
        //autorelease, because the Create Rule only applies to CoreFoundation functions 
        return [[[Fruit alloc] init] autorelease]; 
    }
  2. 實例變量@protected默認。這意味着它們可以被類和任何子類直接訪問。您可以製作它@protected,@private,@public@package。你這樣做是這樣的:

    @interface Apple : Fruit { 
        @private 
        int iSeed 
    } 
    ... 
    @end
  3. 如果你想要一個實例變量是隻讀的,那就不要聲明爲@public,但要一個getter它。例如:

    - (int) iSeeds { 
        return iSeeds; 
    }
  4. 但是,由於實例變量是隻讀的,因此不能在外部進行設置。解決這個問題的辦法是給蘋果初始化期間iSeed值:

    - (id) initWithSeeds:(int)aniSeedValue { 
        if (self = [super init]) { 
        iSeed = aniSeedValue; 
        } 
        return self; 
    }

    然後讓你createAppleWithColor:(int)iSeeds方法,如:

    + (Fruit *) createAppleWithColor:(int)iSeeds { 
        return [[[Apple alloc] initWithSeeds:iSeeds] autorelease]; 
    }
  5. 最後,你應該閱讀Naming Conventions guideMemory Management guide

+0

的便捷構造通常只'fruit'。 – Chuck 2010-05-19 14:34:04

+0

@Chuck,同意。我剛剛添加了一個鏈接去看看命名約定:) – 2010-05-19 14:36:04

+0

我明白了。我仍然有很多東西需要學習。 關於命名約定:我得看看我能否和他們一起生活。我來自C#,目前我不願意接受這種晦澀的ObjectiveC風格,但最終我會採納它。 :-) 我什麼都不明白:「createAppleWithColor」是Apple類中的一種方法。爲什麼它不能訪問Apple的iSeed會員?在C#中,一個方法是靜態的並不重要,它仍然是類的成員。 – Krumelur 2010-05-21 18:08:03

1

還有一件事。如果您有適用於類工廠方法和它的子類,你可以(也許應該)做:

+(Fruit*) fruit 
{ 
    [[[self alloc] init] autorelease]; 
} 

這意味着,如果你調用一個子類的方法,你會得到一個對象正確的類型,例如

Fruit* apple = [Apple fruit]; 

當然,你需要爲蘋果的init方法,它提供了iSeeds合適的默認值,然後調用-initWithSeeds: