Objective-C基础:子类化和成员变量可访问性

时间:2010-05-19 14:19:56

标签: objective-c

下面的代码是伪代码。 想象一下“水果”这一类,它有一种工厂方法来制作水果。

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

现在我想将Fruit子类化为Apple:

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

问题:

  • 如何将“iSeeds”设为私有,以便不能从外部更改?如果我添加“私有”关键字,则不再构建它。
  • 我还想在Apple的工厂方法中设置iSeeds。
  • 我希望用户允许阅读iSeeds的内容。所以我想我应该有一个吸气剂,但我不能让它起作用。我总是得到一些关于“LValue赋值”的错误。
  • Fruit的createFruit正在使用自动释放。 Apple是否必须重新发布/发布任何内容?

2 个答案:

答案 0 :(得分: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. 但是,由于实例变量是readonly,因此无法在外部进行设置。解决这个问题的方法是在初始化期间给Apple一个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

答案 1 :(得分:1)

还有一件事。如果你有一个适用于类及其子类的工厂方法,你可以(可能应该)这样做:

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

这意味着如果您使用子类调用该方法,您将获得一个正确类型的对象,例如。

Fruit* apple = [Apple fruit];

当然,您需要为Apple提供一个init方法,为iSeeds提供合适的默认值,然后调用-initWithSeeds: