0

我目前正在使用 Big Nerd Ranch 指南(第 2 版)自学 Objective-C,直到第 21 章我都没有遇到问题。我查看了这本书的论坛,但没有任何帮助,因为那里的大多数人都是新手意大利面条代码,我不想养成坏习惯......我也是初学者,因为这是我的第一个主要语言,但是意大利面条代码当你看到它时很明显。

我必须从前一章中获取我的代码,并制作一个工具来创建 BNRPortfolio 类的实例并用股票持有量填充它(还必须总结投资组合的当前价值)。然后我必须向 BNRStockHolding 添加一个符号属性,它将股票代码符号保存为 NSString。

我完全不知道在哪里添加代码来执行此操作以及如何开始。根据我的在线研究,这一章写得不好,是大多数读者陷入困境的地方……作者甚至同意在未来的版本中(如果曾经因为 Swift 加入)他们将重新编写整章。

目前,我上一章的代码如下所示:

BNStockHolding.h

#import <Foundation/Foundation.h>

@interface BNRStockHolding : NSObject

@property (nonatomic) float purchaseSharePrice;
@property (nonatomic) float currentSharePrice;
@property (nonatomic) int numberOfShares;

- (float)costInDollars;
- (float)valueInDollars;

@end

BNRStockholding.m

#import "BNRStockHolding.h"

@implementation BNRStockHolding

- (float)costInDollars
{
    return _purchaseSharePrice * _numberOfShares;
}

- (float)valueInDollars
{
    return _currentSharePrice * _numberOfShares;
}

@end

接下来,我必须添加具有将价值和成本转换为美元的转换率的外国股票:

BNRForeignStockHolding.h

#import <Foundation/Foundation.h>
#import "BNRStockHolding.h"

@interface BNRForeignStockHolding : BNRStockHolding

@property (nonatomic) float conversionRate;

@end

BNRForeignStockHolding.m

#import "BNRForeignStockHolding.h"

@implementation BNRForeignStockHolding : BNRStockHolding

- (float)costInDollars
{
    float foreignCostInDollars = super.costInDollars;
    return _foreignCostInDollars * _conversionRate;
}
- (float)valueInDollars
{
    float foreignValueInDollars = super.valueInDollars;
    return _foreignValueInDollars * _conversionRate;
}

@end

我的主文件: main.m

#import <Foundation/Foundation.h>
#import "BNRForeignStockHolding.h"

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

        BNRStockHolding *stock0 = [[BNRStockHolding alloc]init];
        BNRStockHolding *stock1 = [[BNRStockHolding alloc]init];
        BNRStockHolding *stock2 = [[BNRStockHolding alloc]init];
        BNRForeignStockHolding *stock3 = [[BNRForeignStockHolding alloc]init];

        stock0.purchaseSharePrice=2.30;
        stock0.currentSharePrice=4.50;
        stock0.numberOfShares=40;

        stock1.purchaseSharePrice=12.19;
        stock1.currentSharePrice=10.56;
        stock1.numberOfShares=90;

        stock2.purchaseSharePrice=45.10;
        stock2.currentSharePrice=49.51;
        stock2.numberOfShares=210;

        stock3.purchaseSharePrice=43.05;
        stock3.currentSharePrice=28.31;
        stock3.numberOfShares=15;
        stock3.conversionRate=0.3;

        NSMutableArray *stocks = [NSMutableArray arrayWithObjects:stock0, stock1, stock2, stock3, nil];
        for (BNRForeignStockHolding *s in stocks) {
            float a = s.purchaseSharePrice;
            float b = s.currentSharePrice;
            int c = s.numberOfShares;

             if ([s isMemberOfClass:[BNRForeignStockHolding class]]) {

                float d = s.foreignCostInDollars;
                float e = s.foreignValueInDollars;
                NSLog(@"\n Purchase Price: %.2f\n Current Price: %.2f\n Number of Shares %d\n Cost in Dollars %f\n Value in Dollars %f\n", a, b, c, d, e);
            }
            else {

                float d = s.costInDollars;
                float e = s.valueInDollars;
                NSLog(@"\n Purchase Price: %.2f\n Current Price: %.2f\n Number of Shares %d\n Cost in Dollars %f\n Value in Dollars %f\n", a, b, c, d, e);
            }

            }
    }
    return 0;
}

我试过这个:

在 BNRStockHolding.h 中,我创建了一个实例变量:

- (float)currentTotalValue

在 BNRStockHolding.m 中,我是这样实现的:

-(float)currentTotalValue
{
return _currentTotalValue = _currentSharePrice * _numberOfShares;
}

然后在 main.m 中,我将其添加到我的股票数组中的“for”函数中:

float f = s.currentTotalValue;

然后将 %.2f@, f 添加到我的 NSLog 打印输出中。

除了这个警告之外,它工作得很好:

它只是给了我每只股票的价值,而没有转换外国股票。我有点明白为什么,但是这一章没有彻底解释如何解决这样的问题,所以我完全迷失了。我什至无法尝试添加股票代码,因为我不确定在哪里实现它。

将我的投资组合的总价值手动加起来,包括转换后的外国价值,总价值应该是 17,774.895 美元。请记住,这些股票是假装的,转换率等也是如此。

感谢您的帮助,非常感谢!

编辑添加

问题解决了,我不得不重写我的 BNRStock 和 BNRForeign .h 和 .m 文件,覆盖 costInDollars 和 valueInDollars,并为 NSLog 添加一个例外,以通过 [NSString stringWithFormat:] 方法为每个文件打印单独的结果。然后我添加了推荐的总和代码,并进行了一些调整,一切都运行良好。我还通过在我的 .h 和 .m 文件中将 symbol 定义为指针,然后将它们包含在 [NSString stringWithFormat:] 打印输出命令中,从而毫无问题地添加了股票代码。

感谢 danH 注意到我的 costInDollars 和 valueInDollars 应该被覆盖以适用于 BNRStock 和 BNRForeign 类,因为这是我的程序的主要问题。

4

2 回答 2

0

不熟悉这本书,但听起来 BNRPortfolio 是一个新类,值得一个新的 .h 和 .m 文件。您应该从迄今为止所做的工作中借鉴命名约定。开始看起来像这样:

// in BNRPortfolio.h

@class BNRStockHolding;

@interface BNRPortfolio : NSObject

- (void)addHolding:(BNRStockHolding *)holding;
- (float)portfolioValue;

@end

// in BNRPortfolio.m

#import "BNRPortfolio.h"
#import "BNRStockHolding.h"

@interface BNRPortfolio ()  // fixed typo here
@property (strong, nonatomic) NSMutableArray holdings;
@end

@implementation BNRPortfolio

- (id)init {
    self = [super init];
    if (self) {
        _holdings = [NSMutableArray array];
    }
    return self;
}

- (void)addHolding:(BNRStockHolding *)holding {
    [self.holdings addObject:holding];
}

- (float)portfolioValue {
    float sum = 0;
    for (BNRStockHolding *holding in self.holdings) {
        sum += [holding valueInDollars];
    }
    return sum;
}

@end

您应该能够分配初始化其中之一,然后添加几个持股,外国和国内,然后询问投资组合价值。

编辑 - 这样从 main 调用它:

#import <Foundation/Foundation.h>
#import "BNRStockHolding.h"
#import "BNRForeignStockHolding.h"
#import "BNRPortfolio.h"

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

    // build stock0, stock1, stock2, stock3 just as you have them, then...

    BNRPortfolio *portfolio = [[BNRPortfolio alloc] init];

    [portfolio addHolding:stock0];
    [portfolio addHolding:stock1];
    [portfolio addHolding:stock2];
    [portfolio addHolding:stock3];

    NSLog(@"The total value of the portfolio in USD is %f", [portfolio portfolioValue]);
    }
return 0;

}

于 2015-02-15T02:40:56.430 回答
0

我可能只是愚蠢,但我没有在您的代码中看到您汇总了整个投资组合的价值。我看到每只股票的总价值是在哪里计算的。也许您需要在 for 循环之外:

float f = 0.0;

然后在for循环内:

f += e;

这里也只是对可能采用不同方法的一些想法。

我认为我不会在 main.m 中添加任何代码。我将其保留为:

#import <Cocoa/Cocoa.h>

int main(int argc, const char * argv[])
{
    return NSApplicationMain(argc, argv);
}

我会在 Objective C 类中完成这项工作,有很多方法可以做到这一点,但这里有一个(省略了一些细节):

我会启用 ARC,所以我不需要担心内存管理。

在我的 AppDelegate.h 文件中,我可能有:

#import <Foundation/Foundation.h>
#import "BNRStockHolding.h"
#import "BNRPortfolio.h"
#import "BNRForeignStockHolding.h

@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate>

{
    @public

    BNRStockHolding *bnrStockHolding;
    BNRPortfolio *bnrPortfolio;
    BNRForeignStockHolding *bnrForeignStockHolding; 
}

然后在 AppDelegate.m 文件中:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    bnrStockHolding = [[BNRStockHolding alloc] init;
    bnrPortfolio = [[BNRPortfolio alloc] init];
    bnrForeignStockHolding = [[BNRForeignStockHolding alloc] init];

}

然后在 .h 文件中的另一个类(比如说 BNRPortfolio)中,我可能有:

@class AppDelegate;

@interface BNRPortfolio : NSObject

{

    @public

    NSMutableArray *holdings;

    @private

    AppDelegate *appDelegate;
}

- (void)addHolding:(BNRStockHolding *)holding;
- (float)portfolioValue;

在 BNRPortfolio.m 文件中:

#import "BNRPortfolio.h"
#import "AppDelegate.h"

@implementation BNRPortfolio

- (id)init 
{
    self = [super init];
    if (self) 
    {
        holdings = [[NSMutableArray alloc]init];
        appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
    }
    return self;
}

如果您在其他类中设置变量和 AppDelegate 指针,那么在这些类中,例如,可以像这样访问portfolioValue 方法:

float portValue = [appDelegate->brnPortfolio portfolioValue];

和馆藏可以像这样访问:

[appDelegate->brnPortfolio->holdings addObject:holding];

这显然只是应用程序的一个框架(但它已经太长了),但我希望你能明白。在编程中,总是有很多方法可以完成任务,有时一种方法比另一种更好,具体取决于具体情况。我只是碰巧很少使用 main.m。

最后一条评论是,我们在类 .h 文件中使用 @class AppDelegate 并在 .m 文件中导入 AppDelegate.h 的原因是,否则会设置循环引用,编译器不允许这样做。

即 AppDelegate.h 正在导入 BNRPortfolio.h,而 BNRPortfolio.h 将导入 AppDelegate.h。那是循环引用。

所以我们使用@class 语句告诉编译器暂时不要担心,我们稍后会定义类,然后我们在类.m 文件中导入AppDelegate.h。

于 2015-02-16T10:29:46.343 回答