Challenge Solution Utilizing addYourselfToArray

Here is a solution to the Challenge utilizing the addYourselfToArray method given in the book. I have named the method addSelfToArray in the following code.

StockHolding.h

[code]#import <Foundation/Foundation.h>

@interface StockHolding : NSObject
{
float purchaseSharePrice;
float currentSharePrice;
int numberOfShares;
}

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

  • (float)costInDollars;
  • (float)valueInDollars;
  • (void)addSelfToArray:(NSMutableArray *)array;

@end[/code]

StockHolding.m

[code]#import “StockHolding.h”

@implementation StockHolding

@synthesize purchaseSharePrice, currentSharePrice, numberOfShares;

  • (float)costInDollars
    {
    return [self purchaseSharePrice] * [self numberOfShares];
    }

  • (float)valueInDollars
    {
    return [self currentSharePrice] * [self numberOfShares];
    }

  • (void)addSelfToArray:(NSMutableArray *)array;
    {
    return[array addObject:self];
    }
    @end[/code]

ForeignStockHolding.h

[code]#import “StockHolding.h”

@interface ForeignStockHolding : StockHolding
{
float conversionRate;
}
@property float conversionRate;

@end[/code]

ForeignStockHolding.m

[code]#import “ForeignStockHolding.h”

@implementation ForeignStockHolding

@synthesize conversionRate;

  • (float)costInDollars
    {
    float foreignCostInDollars = [super costInDollars];
    return foreignCostInDollars * [self conversionRate];
    }

  • (float)valueInDollars
    {
    float foreignValueInDollars = [super valueInDollars];
    return foreignValueInDollars * [self conversionRate];
    }
    @end[/code]

main.m

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

@autoreleasepool {
    
    // Create instances of the class StockHolding
    StockHolding *stockHolding1 = [[StockHolding alloc] init];
    StockHolding *stockHolding2 = [[StockHolding alloc] init];
    ForeignStockHolding *stockHolding3 = [[ForeignStockHolding alloc] init];

    // Create a mutalbe Array to hold instances of the StockHolding and ForeignStockHolding Classes
    NSMutableArray *stockHoldings = [[NSMutableArray alloc] init];
    
    // Add variables and methods to each instance then add that instant to the stockHoldings array
    [stockHolding1 setNumberOfShares:25];
    [stockHolding1 setPurchaseSharePrice:2.30];
    [stockHolding1 setCurrentSharePrice:4.50];
    [stockHolding1 costInDollars];
    [stockHolding1 valueInDollars];
    [stockHolding1 addSelfToArray:stockHoldings];
    
    [stockHolding2 setNumberOfShares:50];
    [stockHolding2 setPurchaseSharePrice:2.30];
    [stockHolding2 setCurrentSharePrice:4.50];
    [stockHolding2 costInDollars];
    [stockHolding2 valueInDollars];
    [stockHolding2 addSelfToArray:stockHoldings];
    
    [stockHolding3 setNumberOfShares:50];
    [stockHolding3 setPurchaseSharePrice:2.30];
    [stockHolding3 setCurrentSharePrice:4.50];
    [stockHolding3 costInDollars];
    [stockHolding3 valueInDollars];
    [stockHolding3 setConversionRate:0.94];
    [stockHolding3 addSelfToArray:stockHoldings];
    
    // Itterate through the array printing out the values of each
    for (StockHolding *n in stockHoldings) {
        NSLog(@"\n Purchase Price: %.2f\n Current Price: %.2f\n Number Of Shares: %i\n Cost In Dollars: %.2f\n Value In Dollars: %.2f", [n purchaseSharePrice], [n currentSharePrice], [n numberOfShares], [n costInDollars], [n valueInDollars]);
    }
    
}
return 0;

}[/code]

output
2012-03-31 23:43:36.172 StockTwo[2121:403]
Purchase Price: 2.30
Current Price: 4.50
Number Of Shares: 25
Cost In Dollars: 57.50
Value In Dollars: 112.50
2012-03-31 23:43:36.175 StockTwo[2121:403]
Purchase Price: 2.30
Current Price: 4.50
Number Of Shares: 50
Cost In Dollars: 115.00
Value In Dollars: 225.00
2012-03-31 23:43:36.175 StockTwo[2121:403]
Purchase Price: 2.30
Current Price: 4.50
Number Of Shares: 50
Cost In Dollars: 108.10
Value In Dollars: 211.50

Nice and very elegant. I especially like the use of the [self, instead of accessing the ivars directly. I am going to update mine to incorporate this. Thanks.

If you declare that the method return nothing (void), you shouldn’t return anything. Here’s what it should look like:

- (void)addSelfToArray:(NSMutableArray *)array; { [array addObject:self]; }

I’m surprised the compiler let you get away with that one.

It most likely just kept quiet because of the Apple LLVM compiler 3.x Warnings setting: Mismatched Return Type set to NO:

[code]void Bar ();

int Foo ()
{
Bar ();
return 0;
}

void Bar ()
{
return 99;
// Compiler will emit a warning like “void function Bar should not return a value”
// if the setting ‘Mismatched Return Type’ is set to YES
}[/code]

I did exactly the same solution but can anyone explain to me how the for loop knows to loop to the ForeignStockHolding object since its looping by object from my assumption.

// Itterate through the array printing out the values of each
for (StockHolding *n in stockHoldings) {
NSLog(@"\n Purchase Price: %.2f\n Current Price: %.2f\n Number Of Shares: %i\n Cost In Dollars: %.2f\n Value In Dollars: %.2f", [n purchaseSharePrice], [n currentSharePrice], [n numberOfShares], [n costInDollars], [n valueInDollars]);
}

Hey ryangrg
You really seem to know what you are doing
Can anyone walk me through this code explaining step by step what we are doing and why? I am getting so confused on everything! :frowning:

[quote=“kingnathanal”]I did exactly the same solution but can anyone explain to me how the for loop knows to loop to the ForeignStockHolding object since its looping by object from my assumption.

// Itterate through the array printing out the values of each
for (StockHolding *n in stockHoldings) {
NSLog(@"\n Purchase Price: %.2f\n Current Price: %.2f\n Number Of Shares: %i\n Cost In Dollars: %.2f\n Value In Dollars: %.2f", [n purchaseSharePrice], [n currentSharePrice], [n numberOfShares], [n costInDollars], [n valueInDollars]);
}[/quote]

This is an interesting question indeed. Have you figured out why?

Because ForeignStockHolding class inherits from StockHolding class:

@interface ForeignStockHolding : StockHolding
...
@end

A ForeignStockHolding object can behave like a StockHolding object.

And given that the stockHoldings array contains also ForeignStockHolding objects.

Therefore, the loop:

for (StockHolding *n in stockHoldings) {
{
   NSLog (@"...", ...);
}

will print also ForeignStockHolding objects.

[quote=“Sarkha”][quote=“kingnathanal”]I did exactly the same solution but can anyone explain to me how the for loop knows to loop to the ForeignStockHolding object since its looping by object from my assumption.

// Itterate through the array printing out the values of each
for (StockHolding *n in stockHoldings) {
NSLog(@"\n Purchase Price: %.2f\n Current Price: %.2f\n Number Of Shares: %i\n Cost In Dollars: %.2f\n Value In Dollars: %.2f", [n purchaseSharePrice], [n currentSharePrice], [n numberOfShares], [n costInDollars], [n valueInDollars]);
}[/quote]

This is an interesting question indeed. Have you figured out why?[/quote]

As a hands-on way to answer your question try this within the fast enumeration:

NSLog("The class of this stock is %@",n);

You will see that some of them will be the BNRStockHolding class while some will be BNRForeignStockHolding sub class. If it is the former it will use that class’ calculation method but if it is the latter it will start with the over-ride in the foreign sub class.

You are using a lot of redundant code within your header files as you are not only declaring variables but also properties of the same name

For example

[code]#import <Foundation/Foundation.h>

@interface StockHolding : NSObject
{
float purchaseSharePrice;
float currentSharePrice;
int numberOfShares;
}

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

  • (float)costInDollars;
  • (float)valueInDollars;
  • (void)addSelfToArray:(NSMutableArray *)array;

@end[/code]

Instead simply do

[code]#import <Foundation/Foundation.h>

@interface StockHolding : NSObject

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

  • (float)costInDollars;
  • (float)valueInDollars;
  • (void)addSelfToArray:(NSMutableArray *)array;

@end[/code]