【问题标题】:Fast Enumeration on Array with similar Objects具有相似对象的数组的快速枚举
【发布时间】:2014-08-03 00:06:07
【问题描述】:

我对使用填充有相似对象的数组进行快速枚举感到很困惑

假设:

我有 1 个类(Stock Class),它有 1 个子类 ForeignStock。

股票类的属性:

@property float purchaseSharePrice,currentSharePrice;
@property int numberOfShares;

ForeignStock 的属性

@property float conversionRate;

我将上述 2 中的实例放入 MutableArray。如何使用快速枚举显示(NSLog)这两个不同的对象?

 int i = 1;
    for (StockHolding *iterate in shelf) {

        if ([iterate isMemberOfClass:[StockHolding class]])
        {

            NSLog(@"============ Properties of Stock Value %i ============",i);
            NSLog(@"purchase price is  %f",iterate.purchaseSharePrice);
            NSLog(@"current price is %f",iterate.currentSharePrice);
            NSLog(@"number of shares bought is %i",iterate.numberOfShares);

            NSLog(@"--------------Total Value & Cost--------------");
            NSLog(@"Value in dollar for this stock is %f",iterate.valueInDollars);
            NSLog(@"Cost in dollar for this stock is %f",iterate.costInDollars);


            i++;
        }
        else{
            for (ForeignStockHolding *iterate1 in shelf) {
                if ([iterate1 isMemberOfClass:[ForeignStockHolding class]]) {
                    NSLog(@"============ Properties of Stock Value %i  ============",i);
                    NSLog(@"purchase price is  %f",iterate1.purchaseSharePrice);
                    NSLog(@"current price is %f",iterate1.currentSharePrice);
                    NSLog(@"number of shares bought is %i",iterate1.numberOfShares);

                    NSLog(@"--------------Total Value, Cost, & Conversion Rate --------------");
                    NSLog(@"Value in dollar for this stock is %f",iterate1.valueInDollars);
                    NSLog(@"Cost in dollar for this stock is %f",iterate1.costInDollars);
                    NSLog(@"Conversion rate for this stock is %f",iterate1.conversionRate);

                    i++;
                }
            }
        }
    }

上面的代码没有成功,ForeignStock NSLogged 的​​输出为每个 ForeignStock 实例输出 2 次(我知道,第二次快速枚举的方法是错误的)。

如何构建快速枚举,它可以使数组中每个对象的类不同,对每个类子类对象进行不同的处理?

【问题讨论】:

  • 您的问题涉及StockForeignStock 类,但您的代码引用了StockHoldingForeignStockHolding。如果你让它们匹配会有所帮助。
  • 您可以使用isKindOfClass 来完成此操作,但更好的方法是将一个方法放入父类和子类中,以执行您需要的任何操作,然后在循环中简单地调用它......让对象找出正确的行为。多态性...有效! :)
  • 糟糕的设计。使ForeignStockHolding 成为StockHolding 的子类。实现-printInfo 方法(或类似方法)。 StockHolding如上所示,ForeignStockHolding调用[super printInfo],然后打印转化率。一般来说,您永远不想将复杂的类知识实现到其他类中,这不是面向对象编程的意义所在。

标签: objective-c for-loop nsmutablearray fast-enumeration


【解决方案1】:

如果您试图解决的问题是为了获得一个对象的良好表示以进行调试,那么请考虑在您的类中覆盖 -description 方法。以下是这两个类的示例:

@implementation StockHolding

- (NSString *)description
{
    NSString *objectDescriptionFormat = 
    @"============ Properties of Stock Value %@ ============\n"
    "purchase price is  %f\n"
    "current price is %f\n"
    "number of shares bought is %i\n"
    "\n"
    "--------------Total Value & Cost--------------\n"
    "Value in dollar for this stock is %f\n"
    "Cost in dollar for this stock is %f\n";

    return [NSString stringWithFormat:objectDescriptionFormat, 
        [super description],
        self.purchaseSharePrice,
        self.currentSharePrice,
        self.numberOfShares,
        self.valueInDollars,
        self.costInDollars];
}

@end


@implementation ForeignStockHolding

- (NSString *)description
{
    NSString *objectDescriptionFormat = 
    @"%@"
    "Conversion rate for this stock is %f\n";

    return [NSString stringWithFormat:objectDescriptionFormat, 
        [super description],
        self.conversionRate];
}

@end

记录对象变得很容易,因为您只需记录对象,描述就会打印在控制台上。

for (StockHolding *stockHolding in shelf)
{
    NSLog(@"%@", stockHolding);
}

【讨论】:

  • [super description] 在您的代码中显示对象的地址,是否可以使其显示对象的名称?例如,我创建 StockHolding 的实例,称为 StockHolding1、StockHolding2、...然后它将显示 StockHolding1、StockHolding2,而不是它的地址。
  • StockHolding1 是变量的名称,还是对象的属性?
【解决方案2】:

根据isMemberOfClass: 调用的结果决定要做什么通常表明您错过了继承的机会:在大多数情况下,正确的解决方案是向基类添加一个方法,然后重写它在派生类中。

在这种特定情况下,请考虑覆盖一个名为 description 的现有方法,该方法继承自 NSObjectStockHoldingForeignStockHolding 都应该提供一个实现:

// This implementation goes in StockHolding
-(NSString*)description {
    return [NSString stringWithFormat:@"purchase price is  %f\n"
        "current price is %f\n"
        "number of shares bought is %i\n"
        "--------------Total Value & Cost--------------\n"
        "Value in dollar for this stock is %f\n"
        "Cost in dollar for this stock is %f"
    ,   _purchaseSharePrice
    ,   _currentSharePrice
    ,   _numberOfShares
    ,   _valueInDollars
    ,   _costInDollars
    ];
}
// This implementation goes into ForeignStockHolding
-(NSString*)description {
    return [NSString stringWithFormat:@"%@\n"
        "Conversion rate for this stock is %f"
    ,   [super description]
    ,   _ conversionRate
    ];
}

有了这两个实现,您可以统一记录所有数据,如下所示:

for (StockHolding *item in shelf) {
    NSLog(@"%@", item);
}

【讨论】:

  • 您可能希望将 -display 重命名为 -description。它在您的答案中正确提及,但在代码 sn-p 中未提及。
  • @Anurag 你说得对,我说的是在正文中覆盖description,然后在示例中将其称为display!谢谢!
【解决方案3】:

这是一种方法:

int i = 1;
for (StockHolding *iterate in shelf) {

    NSLog(@"============ Properties of Stock Value %i ============",i);
    NSLog(@"purchase price is  %f",iterate.purchaseSharePrice);
    NSLog(@"current price is %f",iterate.currentSharePrice);
    NSLog(@"number of shares bought is %i",iterate.numberOfShares);

    if ([iterate isKindOfClass:[ForeignStockHolding class]])
        NSLog(@"--------------Total Value, Cost, & Conversion Rate --------------");
    else
        NSLog(@"--------------Total Value & Cost--------------");

    NSLog(@"Value in dollar for this stock is %f",iterate.valueInDollars);
    NSLog(@"Cost in dollar for this stock is %f",iterate.costInDollars);

    if ([iterate isKindOfClass:[ForeignStockHolding class]])
        NSLog(@"Conversion rate for this stock is %f", ((ForeignStockHolding*)iterate).conversionRate);

    i++;
}

您不想要第二个for 循环,您只想根据类调整行为。当您测试该类时,我建议您测试该对象是否是专用子类的一个实例,而不是它是完全基类的一个实例。

但是,测试对象的类通常是代码异味。通常最好让一个类定义自己的行为,然后让客户端代码简单地要求对象执行该行为。因此,例如,可以要求对象描述自己。 StockHolding 类将生成包含其属性的描述字符串。 ForeignStockHolding 类将调用 super 来获取基本描述,然后使用它添加的属性添加到它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 2011-12-12
    • 1970-01-01
    • 1970-01-01
    • 2020-05-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多