2015-02-15 7 views
0

В настоящее время я преподаю себе Objective-C с руководством Big Nerd Ranch (2-е издание), и у меня не было проблемы до главы 21. Я проверил форум книги, но это не помогло, потому что у большинства людей есть новички с кодом спагетти, и я не хочу принимать вредные привычки ... Я тоже начинаю, поскольку это мой первый основной язык, но код спагетти очевиден, когда вы его видите.Попытка создать портфель акций с общей стоимостью в Objective-C, но не уверен в подходе

Мне нужно взять мой код из предыдущей главы и создать инструмент, который создает экземпляр класса BNRPortfolio и заполняет его запасами (также должен суммировать текущее значение портфеля). Затем мне нужно добавить свойство символа в 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 

Далее, я должен был добавить иностранные акции с коэффициентом конверсии, который преобразил ценности и стоимость в куклу США АРС:

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; 
} 

Затем в основной .m, я добавил это к функции «для» в моем запасе:

float f = s.currentTotalValue; 

Затем добавили% .2f @, f в мою распечатку NSLog.

Он работал отлично для этого предостережения, за исключением:

Он просто дал мне ценность каждой отдельной акции без конвертации иностранных акций. Я несколько понимаю, почему, но глава не объяснила подробно, как атаковать такую ​​проблему, поэтому я полностью потерян.Я даже не мог попытаться добавить символ биржевого кода, потому что не был уверен, где его реализовать.

При суммировании общей стоимости моего портфеля вручную конвертированные иностранные значения включаются в общую сумму 17 774,895 долларов США. Имейте в виду, что эти запасы притворяются, равно как и коэффициент конверсии и т. Д.

Благодарим за помощь, будем благодарны!

EDIT ДОБАВИТЬ

Проблема решена, мне пришлось переписать мои BNRStock и BNRForeign .h и .m файлы с переопределением для costInDollars и valueInDollars, а также добавить исключение для NSLog распечатать отдельные результаты для каждого с помощью метода [NSString stringWithFormat:]. Затем я добавил код суммы, рекомендованный несколькими настройками, и все сработало хорошо. Я также добавил, что биржевые тикеры не представляют проблемы, указав символ в качестве указателя в моих файлах .h и .m, а затем включив их в команду [NSString stringWithFormat:] printout.

Shoutout to danH, заметив, что моя стоимостьInDollars и valueInDollars должны быть переопределены для работы как для классов BNRStock, так и для BNRForeign, поскольку это было основной проблемой моей программы.

ответ

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 

Вы должны быть в состоянии Alloc-INIT один из них, а затем добавить несколько холдингов, иностранных и отечественных, а затем попросить стоимости портфеля.

EDIT - вызвать из главного таким образом:

#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; 

}

+0

Спасибо! Я попробую это очень скоро и вернусь к вам. Я решил, что мне, возможно, придется создать новый класс, но не был уверен. Еще раз спасибо, я ценю это! – Yistorian

+0

Я добавил еще один связанный с этим вопрос, все еще работая с примером, который вы предоставили. Я думаю, что есть некоторые странные ошибки в моих заголовочных файлах и файлах реализации, но я не уверен, что. – Yistorian

+0

Я не думаю, что вы должны добавить что-нибудь в заголовок. Проблема, с которой вы столкнулись, связана с кодом вызова. Не следует пытаться вызвать foreignValueInDollars. Нет такого понятия. Пункт упражнения заключается в том, что иностранный и отечественный фонды делают то же самое для вас, что говорит вам их стоимость в долларах, хотя используется более сложное уравнение, подкласс скрывает это для вас. – danh

0

Я может быть просто тупой, но я не вижу в вашем коде, где вы на общую сумму всей стоимости портфеля. Я вижу, где вычисляется общая стоимость каждого запаса. Может быть, вам нужно вне цикл:

float f = 0.0; 

затем внутри для цикла:

f += e; 

Вот и всего пару мыслей о, может быть другой подход.

Я не думаю, что я бы поставил код в main.m. Я бы оставить его, как:

#import <Cocoa/Cocoa.h> 

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

Я хотел бы сделать работу в объективных классах С, и существует целый ряд способов сделать это, но вот один (выезд некоторых деталей):

Я бы включил 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.м файла:

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

} 

Тогда в другом классе (позволяет говорить BNRPortfolio) в .h файле, я мог бы иметь:

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

Последний комментарий: причина, по которой мы говорим @class AppDelegate в файлах .h и импортировании AppDelegate.h в файлы .m, заключается в том, что иначе будет создана круговая ссылка, которую компилятор не позволит ,

Это приложение AppDelegate.h импортирует BNRPortfolio.h и BNRPortfolio.h будет импортировать AppDelegate.h. Это круговая ссылка.

Таким образом, мы используем оператор @class, чтобы сообщить компилятору, чтобы он не беспокоился, мы определим класс позже, а затем импортируем AppDelegate.h в файлы класса .m.

+0

Thx за советом, я изучаю его. – Yistorian

+0

Я понял, что да, я был кругом, ссылающимся на все. Я сохранил #imports в файлах заголовков (BNRPort для BNRForeign для BNRStock), но я добавил @class BNRPortfolio в BNRStockHoldings.h, чтобы он знал о подклассах. Это разрешило ошибки моего заголовка и файла реализации. Я также смог удалить две строки «@property» из BNRForeignStockHoldings.h, и эта ошибка также исчезла. Все еще определяя наилучший способ подытожить портфели и добавить биржевые тикеры (что является более простой частью). – Yistorian