简体   繁体   English

Objective-C类方法

[英]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 我已经意识到我可以代替PlayingCardselfmaxRank方法没有任何错误消息,但是代替selfPlayingCardsetSuit方法给我一个错误说

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: 如果要发送类方法,则编译器可以使用两种语法:

  1. [ClassName classMethod]
  2. [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. 但是, maxRankrankStrings都是类方法。 Class methods are basically the same as static methods in C++ 类方法与C ++中的静态方法基本相同

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM