试图创建总价值为 Objective-C 的股票投资组合,但不确定该方法

Trying to create a portfolio of stocks with a total value in Objective-C, but unsure of the approach

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

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

我完全不知道在哪里添加代码来执行此操作以及如何开始。根据我在网上的研究,这一章写得不好,这是大多数读者被卡住的地方……作者甚至同意在未来的版本中(如果因为 Swift 搬进来)他们会重写整个章节.

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

BNRStockHolding.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

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

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 文件中将符号定义为指针然后将它们包含在 [NSString stringWithFormat:] 打印输出命令中来毫无问题地添加股票代码。

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

不熟悉这本书,但听起来 BNRPortfolio 是一本新书 class,值得一个新的 .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;

}

我可能只是愚蠢,但我没有在您的代码中看到您在哪里计算整个投资组合的价值。我看到每只股票的总价值是在哪里计算的。也许你需要在 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 classes 中完成这项工作,有很多方法可以做到这一点,但这里有一个(省略一些细节):

我会启用 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 文件中的另一个 class(比方说 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;
}

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

float portValue = [appDelegate->brnPortfolio portfolioValue];

可以像这样访问馆藏:

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

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

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

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

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