【问题标题】:Objective-C Accessing Superclass Methods when Object Might be Superclass or Subclass当对象可能是超类或子类时,Objective-C 访问超类方法
【发布时间】:2015-07-29 20:31:24
【问题描述】:

我是一名 Objective-C 菜鸟,正在学习教程,但遇到了一个奇怪的问题,我想更好地理解。

我正在循环制作一个股票对象组合,这些对象有 50/50 的机会成为“foreignStock”或只是“股票”——不同之处在于转换率属性。对象 stock 是一个超类,foreignStock 是 stock 的子类。

我想创建一个指针,掷硬币来决定它是哪种类型,然后分配我需要的值。既然子类和超类都有currentSharePrice之类的东西,为什么我不能在抛硬币后设置它们呢?

这是我的 main.m 供审查:

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        // Declare portfolio and set the conversion rate
        BNRPortfolio *mikesPortfolio = [[BNRPortfolio alloc] init];
        NSUInteger globalConRate = 1.2;

        // Array of ticker names - remove them as they are used
        NSMutableArray *tickerNames = [[NSMutableArray alloc] init];
        [tickerNames addObject:@"ibm"];
        [tickerNames addObject:@"ppg"];
        [tickerNames addObject:@"google"];
        [tickerNames addObject:@"vrzn"];
        [tickerNames addObject:@"apple"];
        [tickerNames addObject:@"barq"];

        // Create and add the stocks to the portfolio
        for (int i = 0; i < 6; i++) {

            id newStock;

            // Coin flip to determine type
            NSUInteger randomType = random() % 2;
            if (randomType == 0) {

               newStock = [[BNRStockHolding alloc] init];

            } else {

                newStock = [[BNRForeignStockHolding alloc] init];
                newStock.conversionRate = globalConRate;
            }

            // Assign remaining values
            newStock.purchaseSharePrice = 15 * (random() % i);
            newStock.currentSharePrice = newStock.purchaseSharePrice * 1.4;

            NSUInteger randomTickerValue = random() % [tickerNames count];
            newStock.symbol = tickerNames[randomTickerValue];
            [tickerNames removeObjectAtIndex:randomTickerValue];

            [mikesPortfolio addHoldings:newStock];
        }
    }

else{} 块 newStock.conversionRate... 内的行给出了 Xcode 预编译错误,指出“找不到 __strong id 类型的对象的属性” - 我猜是因为它无法判断 newStock 是否真的会我刚刚宣布它是什么?但是 main.m 末尾的分配语句显示了相同的行错误,就好像 newStock 没有这些属性一样,即使两个类都可以访问它们。

我如何让 newStock 明白它肯定是一个具有这些属性但也可能具有与子类相关联的转化率的类?

我试过这个:

        BNRStockHolding newStock;  <-- starting with superclass

        // Coin flip to determine type
        NSUInteger randomType = random() % 2;
        if (randomType == 0) {

           newStock = [[BNRStockHolding alloc] init];

        } else {

            newStock = [[BNRForeignStockHolding alloc] init];
            newStock.conversionRate = globalConRate;
        }

这将使底线的错误消失,但仍无法在 else{} 块中的子类方法处编译。

我哪里做错了?

【问题讨论】:

  • 任何时候你说“抛出错误”,你都需要指出你收到的错误,无论是在编译时还是运行时。

标签: objective-c inheritance scope


【解决方案1】:

(我假设这实际上是main.m,而不是main.c。)

您的主要错误是使用id 而不是类型。

 id newStock;

这表示newStock 是“某种对象,我不知道是什么”。在 ObjC 中,id 可以发送任何消息,但它没有任何属性。所以你不能在上面使用点符号。有一些解决方法(不要使用点表示法),但更好的解决方案是使用类型:

BNRStockHolding *newStock = nil;

这会导致这里出现问题:

newStock = [[BNRForeignStockHolding alloc] init];
newStock.conversionRate = globalConRate;

你可以通过这种方式解决:

BNRForeignStockHolding *foreignStock = [[BNRForeignStockHolding alloc] init];
foreignStock.conversionRate = globalConRate;
newStock = foreignStock;

但是,如果使外国股票“外国”的唯一原因是它具有转换率,我强烈建议不要在这里进行子分类。只要让所有股票都有一个转换率。如果是国内的,转化率为1。

【讨论】:

  • 当我声明:BNRStockHolding *newStock; 我避免了底线的错误,但 else{} 块内的行仅在 newStock 被证明是子类类型时才会触发仍然失败,因为 BNRStockHolding 没有'没有 conversionRate 属性。
  • 请注意我的“您可以通过这种方式解决。”您将对象创建为外国股票,对其进行配置,然后将其分配给newStock。也就是说,这可能不是子类化的好方法。
  • 我很抱歉 - 我很快就发表了评论,错过了您的帖子还有更多内容。我坦率地承认这是对子类化的荒谬使用——它们在书中的使用要简单得多,而且我让扩展继承案例变得复杂。如果我按照您提到的方式修复它,我是否正确地说我现在将有两个指向同一个对象的指针?
  • 是的,您将有两个指针。然后第二个指针 (foreignStock) 将超出} 的范围并消失。在大多数情况下,继承是 ObjC 中的最后选择。它通常由辅助对象(通常是委托)而不是子类组成。祝你好运。
猜你喜欢
  • 2018-07-15
  • 2017-09-13
  • 2016-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-03
  • 1970-01-01
相关资源
最近更新 更多