Krumelur
Krumelur

Reputation: 33058

Objective-C basics: subclassing and member variable accessability

Code below is pseudo code. Imagine a class "Fruit" which has a factory method to create a fruit.

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

Now I want to subclass the Fruit to get an Apple:

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

Questions:

René

Upvotes: 1

Views: 1251

Answers (2)

JeremyP
JeremyP

Reputation: 86661

One more thing. If you have a factory method which applies to a class and its subclasses, you can (probably should) do this:

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

This means that if you invoke the method with a subclass, you'll get an object of the right type e.g.

Fruit* apple = [Apple fruit];

Of course, you'll need to provide an init method for Apple that provides a suitable default value for iSeeds and then invokes -initWithSeeds:

Upvotes: 1

Dave DeLong
Dave DeLong

Reputation: 243156

A couple things.

  1. Your createFruit method is wrong. It should be:

    + (Fruit *) createFruit {
      //autorelease, because the Create Rule only applies to CoreFoundation functions
      return [[[Fruit alloc] init] autorelease];
    }
  2. Instance variables are @protected by default. That means they can be directly accessed by the class and any subclasses. You can make it @protected, @private, @public, and @package. You do so like this:

    @interface Apple : Fruit {
      @private
      int iSeed
    }
    ...
    @end
  3. If you want an instance variable to be readonly, then don't declare it as @public, but make a getter for it. For example:

    - (int) iSeeds {
      return iSeeds;
    }
  4. However, since the instance variable is readonly, you can't set it externally. The way around this is to give the Apple a iSeed value during initialization:

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

    Then make your createAppleWithColor:(int)iSeeds method like:

    + (Fruit *) createAppleWithColor:(int)iSeeds {
      return [[[Apple alloc] initWithSeeds:iSeeds] autorelease];
    }
  5. Finally, you should read the Naming Conventions guide and the Memory Management guide.

Upvotes: 1

Related Questions