[英]Objective-C Class Method
My header class looks like: 我的标头类如下:
#import "Card.h"
@interface PlayingCard : Card
@property (strong, nonatomic) NSString *suit;
@property (nonatomic) NSUInteger rank;
+ (NSArray *) validSuits;
+ (NSUInteger) maxRank;
@end
And my implementation: 而我的实现:
@implementation PlayingCard
+ (NSArray *) validSuits
{
return @[@"♥︎", @"♣︎", @"♦︎", @"♠︎"];
}
+ (NSArray *) rankStrings
{
return @[@"?", @"1", @"2", @"3", @"4"];
}
- (void)setSuit:(NSString *)suit
{
if ([[PlayingCard validSuits] containsObject:suit])
{
_suit = suit;
}
}
- (NSString *)suit
{
return _suit ? _suit : @"?"; // if suit !nil return suit, else return ? string.
}
+ (NSUInteger)maxRank
{
return [[self rankStrings] count] - 1;
}
@end
So I understand that any method with a + means it's a Class method. 因此,我知道任何带有+的方法都意味着它是一个Class方法。
My question is, why must I use [PlayingCard classMethod]
eg [PlayingCard validSuits]
in the setSuit
method whereas I can use [self classMethod]
eg [self rankStrings]
in the maxRank
method? 我的问题是,为什么一定要我用[PlayingCard classMethod]
如[PlayingCard validSuits]
在setSuit
方法,而我可以用[self classMethod]
如[self rankStrings]
在maxRank
方法?
I'm assuming it's something to do with the maxRank
method being a class method whereas setSuit
isn't. 我假设这与maxRank
方法是类方法有关,而setSuit
不是。 But could it be because setSuit
is a setter? 但这可能是因为setSuit
是setter吗?
I really don't know, I can't visualise what's going on here. 我真的不知道,我无法想象这里发生了什么。 I've only just started my foray into Objective-C and am coming from a Java background. 我只是刚开始涉足Objective-C,并且来自Java背景。
I have realised I can substitute PlayingCard
in for self
in the maxRank
method without any error messages, however substituting self
in for PlayingCard
in the setSuit
method gives me an error saying 我已经意识到我可以代替PlayingCard
为self
的maxRank
方法没有任何错误消息,但是代替self
在PlayingCard
中setSuit
方法给我一个错误说
No visible @interface for 'PlayingCard' declares the selector for 'validSuits'
Any explanation as to why this is the case and what's going on would be great. 关于为何如此以及发生什么的任何解释都很好。 Thanks! 谢谢!
The meaning of self
in methods 方法中self
的意义
Every Objective-C method receives an implicit self
argument. 每个Objective-C方法都接收一个隐式的self
参数。 Instance methods receive the instance, while class methods receive the class object (remember: classes are objects). 实例方法接收实例,而类方法接收类对象(请记住:类是对象)。
If you want to send a class method, the compiler lets you use two types of syntax: 如果要发送类方法,则编译器可以使用两种语法:
[ClassName classMethod]
[classObjectPtr classMethod]
The first syntax is used in [PlayingCard maxRank]
. 第一种语法用于[PlayingCard maxRank]
。 Here, the target is (explicitly) the PlayingCard
class. 在这里,目标是(明确地) PlayingCard
类。
A class method already has a class object as a target for sending class methods: the self
argument. 一个类方法已经有一个类对象作为发送类方法的目标: self
参数。 So they can use [self classMethod]
to send other class methods. 因此他们可以使用[self classMethod]
发送其他类方法。
Why sending a message to self
in class methods? 为什么要在类方法中向self
发送消息?
The advantage of the latter is that the class is not explicitly named. 后者的优点是该类未显式命名。 This makes it possible to override class methods in subclasses and call them from base classes. 这样就可以覆盖子类中的类方法并从基类中调用它们。
You basically get the same dynamic method dispatch as with instance methods. 基本上,您可以获得与实例方法相同的动态方法分配。 This is actually a nice feature of Objective-C not present in Java or C++. 这实际上是Java或C ++中没有的Objective-C的一个不错的功能。
Instance methods would use the dynamic version by accessing their class and sending the message to that: 实例方法将通过访问类并向其发送消息来使用动态版本:
- (void)setSuit:(NSString *)suit
{
if ([[[self class] validSuits] containsObject:suit])
{
_suit = suit;
}
}
Now an imaginary subclass of PlayingCard
could override the class method validSuits
and implicitly alter the behavior of setSuit:
. 现在,虚构的PlayingCard
子类可以覆盖类方法validSuits
并隐式更改setSuit:
的行为。
self
can be an instance or a class depending on the type of method declared. 根据声明的方法类型, self
可以是实例或类。
- (void)setSuit:
is an instance method, thus self
is an instance inside this method declaration. - (void)setSuit:
是一个实例方法,因此self
是此方法声明内的一个实例。
+ (NSUInteger)maxRank
is a class method, thus self
is a class inside inside this method declaration. + (NSUInteger)maxRank
是一个类方法,因此self
是此方法声明内的一个类。
+ (void)classMethod;
- (void)instanceMethod;
- (void)setSuit
{ // self is an instance here
[self classMethod]; // warning, class method sent to instance
[self instanceMethod]; // works, instance method sent to instance
}
+ (NSUInteger)maxRank
{ // self is a class here
[self classMethod]; // works, class method sent to class
[self instanceMethod]; // warning, instance method sent to class
}
You tried to called a "class method" on self
inside an instance method where self
in an "instance". 您试图在实例方法中的self
内调用self
的“类方法”。
In a class method, self
refers to the class (it refers to an object that represents the class that obj-c runtime creates for you), so you can use it to call class level method. 在类方法中, self
是指类(它是表示obj-c运行时为您创建的类的对象),因此您可以使用它来调用类级别的方法。
In an instance method, self
refers to the instance. 在实例方法中, self
是指实例。 If you want to call class level method in an instance method, you need to use the class name instead. 如果要在实例方法中调用类级别的方法,则需要改用类名。
Java analogy of obj-c class methods is the static method. Java类似于obj-c类方法是静态方法。 Java's this
keyword is similar to self
, except it can't be used to refer to a class. Java的this
关键字类似于self
,不同之处在于它不能用于引用类。
setSuit
is an instance method, and validSuits
is a class method. setSuit
是一个实例方法,而validSuits
是一个类方法。 However, both maxRank
and rankStrings
are class methods. 但是, maxRank
和rankStrings
都是类方法。 Class methods are basically the same as static methods in C++ 类方法与C ++中的静态方法基本相同
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.