[Suggestion] No visible @interface for 'StockHolding'


#1

In working on the challenge, I used this as my code:

StockHolding.h:

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

@end

StockHolding.m:

#import "StockHolding.h"

@implementation StockHolding

@synthesize purchaseSharePrice, currentSharePrice, numberOfShares;

- (float)costInDollars
{
    return purchaseSharePrice * numberOfShares;
}
- (float)valueInDollars
{
    return currentSharePrice * numberOfShares;
}

@end

main.m

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

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

    @autoreleasepool {
        
        StockHolding *firstStock = [[StockHolding alloc] init];
        [firstStock purchaseSharePrice:2.30];
        [firstStock currentSharePrice:4.50];
        [firstStock numberOfShares:40];
        
        StockHolding *secondStock = [[StockHolding alloc] init];
        [secondStock purchaseSharePrice:12.19];
        [secondStock currentSharePrice:10.56];
        [secondStock numberOfShares:90];
        
        StockHolding *thirdStock = [[StockHolding alloc] init];
        [thirdStock purchaseSharePrice:45.10];
        [thirdStock currentSharePrice:49.51];
        [thirdStock numberOfShares:210];
        
        NSMutableArray *stocks = [NSArray arrayWithObjects:firstStock, secondStock, thirdStock, nil];
        
    }
    return 0;
}

This seems like it would completely work according to the lessons in the book, but there’s an error that causes the messages “No visible @interface for ‘StockHolding’ declares the selector x” (replace x with the name of the setter method). Here’s my issue with the way the book handles this:

Since we’re using and building off of existing code, there’s no mention that using the @property float purchaseSharePrice and the @synthesize purchaseSharePrice creates a purchaseSharePrice method but also a setPurchaseSharePrice method. We had already typed this into our main.m file because we had created our own individual getter/setter functions using both those names. Since the new @property/@synthesize declarations don’t ever mention a setPurchaseSharePrice (including the case change!) and the book never deals with this, I was under the impression that [first purchaseSharePrice:80.0] would set the value and [first purchaseSharePrice] (without a value) would get the value. This is not the case and it’s not mentioned anywhere in here.

Has anyone else fallen into this trap? Am I the only one that spent 20 minutes trying to find spelling/case errors in my code without realizing this?


#2

When learning a new programming language, familiarity with another language does help greatly. However sometimes this gets in the way, by making us blind to what’s written on the page.

The book does talk about the setter and getter methods in chapter 17, and alludes to the naming conventions briefly in that chapter.


#3

When learning a new programming language, familiarity with another language does help greatly. However sometimes this gets in the way, by making us blind to what’s written on the page.

The book does talk about the setter and getter methods in chapter 17, and alludes to the naming conventions briefly in that chapter.[/quote]

That’s part of the issue, though. I don’t know any other programming languages. I got my impression from when we created the properties and then removed the functions with the word “set” at the beginning that we had initially created. This caused me to think that those functions were no longer needed. Then, when we added the new properties, we only re-added the “set”-less version. I think I understand now that the version with the “set” and the uppercase change is created automatically, right?


#4

Sorry, I had the impression that you were familiar with some other language and the auto-pilot took over :slight_smile:

Only if you use properties. If you don’t use properties, you create manually.

Using property:

@class FooBar;

@interface Foo: NSObject

@property FooBar * fooBar;

@end
...
@implementation Foo

@synthesize fooBar;

@end

Accessor methods fooBar and setFooBar are created automatically.

Not using property:

@class FooBar;

@interface Foo: NSObject
{
FooBar * _fooBar;
}
@end
...
- (FooBar *)fooBar {return _fooBar;}

- (void)setFooBar:(FooBar *)fooBar {_fooBar = fooBar;}

You write the accessor methods fooBar and setFooBar.


#5

Yup… That’s what I thought. The book didn’t mention anywhere that using properties creates a different function for the setProperty. I just got confused because, you’re right, we were explicitly creating that before. Again, I thought the property used the same name and just “knew” whether you were getting or setting based on whether you included a value. That is not the case and the book didn’t mention that.