试图创建总价值为 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 文件。
我目前正在使用 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 文件。