Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing class method in objective c. Using self or classname?

I am learning iOS programming and am confused by the following code regarding the use of keyword self.

From my understanding, self is like Java's this. It refers to the current instance. When I want to call a class method, the usual way should be like [PlayingCard validSuits]; But it's also OK to invade a class method on an instance, right? Like [self validSuits]; (I am in the class so self refers to an instance of PlayingCard)

But in the following code, it gives error somewhere but looks ok elsewhere.(Pointed out by 3 comments, this is within Xcode 5.1)

Am I missing anything?

(P.S. I think I am having the similar problem as here, which no one answered yet. He got the same error even using [PlayingCard validSuits]. )

//  PlayingCard.m

#import "PlayingCard.h"

@implementation PlayingCard
@synthesize suit = _suit; 

+ (NSArray *)validSuits {
    return @[@"♠︎", @"♣︎", @"♥︎", @"♦︎"];
}

+ (NSArray *)rankStrings {
    return @[@"?", @"A", @"2", @"3", @"4",@"5",@"6",@"7",@"8",@"9",@"10",@"J",@"Q",@"K"];

}

+ (NSUInteger)maxRank {
    return [[PlayingCard rankStrings] count] -1; 
          //1. [self rankStrings] works fine.** 
}


//override super class's method
- (NSString *)contents {

    NSArray *rankStrings = [PlayingCard rankStrings];  
           //2. if change rankStrings to self, then error:
           //No visible @interface for 'PlayingCard' declares the selector 'rankStrings'

    return [rankStrings[self.rank] stringByAppendingString:self.suit];
}

- (void) setSuit:(NSString *)suit {
    if ( [[PlayingCard validSuits] containsObject:suit]) {  
        //3.error when changed to [self validsuits] 
        //No visible @interface for 'PlayingCard' declares the selector 'validsuits'**
       _suit = suit;
    }

}

- (NSString *) suit {
    return _suit ? _suit : @"?";
}

@end

The header file:

//  PlayingCard.h

#import "Card.h"

@interface PlayingCard : Card

@property (nonatomic, strong) NSString *suit;
@property (nonatomic) NSUInteger rank;

+ (NSArray *) validSuits;
+ (NSUInteger) maxRank;

@end
like image 846
Weishi Z Avatar asked Apr 12 '14 21:04

Weishi Z


1 Answers

If you are calling another class method from inside a class method (of the same class) you can just use [self classMethod]. If however you are in an instance method and you need to call that classes class method you can use [[self class] classMethod]

As pointed out by @Martin R - if you subclass PlayingCard, calling self in a class method will then be that subclass and not PlayingCard.

EDIT:

For completeness you need to do:

//  PlayingCard.m

#import "PlayingCard.h"

@implementation PlayingCard
@synthesize suit = _suit; 

+ (NSArray *)validSuits {
    return @[@"♠︎", @"♣︎", @"♥︎", @"♦︎"];
}

+ (NSArray *)rankStrings {
    return @[@"?", @"A", @"2", @"3", @"4",@"5",@"6",@"7",@"8",@"9",@"10",@"J",@"Q",@"K"];

}

+ (NSUInteger)maxRank {
    return [[self rankStrings] count] -1; 
}

//override super class's method
- (NSString *)contents {

    NSArray *rankStrings = [[self class] rankStrings];  

    return [rankStrings[self.rank] stringByAppendingString:self.suit];
}

- (void) setSuit:(NSString *)suit {
    if ( [[[self class] validSuits] containsObject:suit]) {  
       _suit = suit;
    }
}

- (NSString *) suit {
    return _suit ? _suit : @"?";
}

@end
like image 143
Rich Avatar answered Nov 15 '22 22:11

Rich