1

我来自 Actionscript 背景。在 Actionscript 中,Class Method 只能访问 Class Methods 和 Class 属性。

但在目标 C 中,

  1. Class方法gameResultAll如何访问Instance方法initFromPlist

    +(NSMutableArray *)gameResultAll://Class Method
    
    -(id)initFromPlist:(id)plist;//Instance Method
    
    NSMutableArray *gameResults = [GameResult gameResultAll]; // (returns GameResult array)
    
  2. 为什么调用 [self init] 方法而不是 [super init] 来从类方法创建实例。

提前致谢。

#import "GameResult.h"

@implementation GameResult

#define GAME_RESULT_KEY @"gameresult_key"
#define SCORE_KEY @"score"

+(NSMutableArray *)gameResultAll
{

    NSMutableArray *resultArray = [[NSMutableArray alloc] init];
    for (id plist in [[[[NSUserDefaults standardUserDefaults] dictionaryForKey:GAME_RESULT_KEY] mutableCopy] allValues]) 
    {
        GameResult *gameResult = [[GameResult alloc] initFromPlist:plist];
        [resultArray addObject:gameResult];
    }
    return  resultArray;
}

//Designated initialiser
-(id)initFromPlist:(id)plist
{

    self = [self init];
    if(self)
    {
       if([plist isKindOfClass:[NSDictionary class]])
       {
           NSDictionary *resultDictionary = (NSDictionary*)plist;
           _score = (int)resultDictionary[SCORE_KEY];
       }
    }
    return  self;
}
4

2 回答 2

2

您问:

Class方法如何gameResultAll访问Instance MethodinitFromPlist

它可以访问该方法,因为您使用了该alloc方法,该方法创建了GameResult. 现在您有了一个实例,您可以将实例方法与该实例结合使用。

顺便说一句,这是一种非常常见的模式,一种“便利”类方法,它分配对象的实例(带有alloc)并初始化对象(带有init或某种排列)。或者,在本例中,它可以创建这些对象的数组。

然后你继续问:

为什么[self init]调用方法而不是[super init]从类方法创建实例。

我可以理解这种混淆,但是这两者的行为有一个重要而微妙的区别。

想象一下这个场景:

  • 在将来的某个日期,您将子类化GameResult,例如ArcadeGameResult

  • 你实现了一个init方法来ArcadeGameResult初始化这个子类独有的一些属性;和

  • 你碰巧ArcadeGameResult像这样初始化一个实例:

    ArcadeGameResult *agr = [[ArcadeGameResult alloc] initFromPlist:plist];
    

因为initFromPlistuses [self init],这意味着 的initFromPlist方法GameResult最终会调用init对象的方法(在这个例子中,它实际上是一个ArcadeGameResult对象)。但是如果改为调用initFromPlist,它就不会调用'方法,因此如果与子类一起使用就会有问题。GameResult[super init]ArcadeGameResultinitinitFromPlist

底线,除非您调用的方法是完全相同的方法签名,否则调用self再现比调用再现更安全super。如果您将来决定子类化,它会更灵活一些。


律师有一个推论。从实例方法调用类方法时,应该引用[self class]而不是类名。所以,假设你的GameResult类有一个类方法:

+ (void)someClassMethod
{
    // do something
}

如果你有一些GameResult实例方法可以利用这个方法,你可能会想写:

- (void)someInstanceMethod
{
    // do some stuff

    [GameResult someClassMethod];
}

但这不是一个好主意。您将改为使用以下内容:

- (void)someInstanceMethod
{
    // do some stuff

    [[self class] someClassMethod];
}

它们看起来非常相似,但后者允许您someClassMethod在子类中实现 a,并且此实例方法仍然有效。如果您使用前一种构造,则子类化的类方法不会被someInstanceMethod.

这些都是微妙的问题,对于您当前的代码示例可能并不重要。[self init]但希望它能阐明[super init]在这种情况下的选择。

于 2013-07-19T06:51:33.270 回答
2

在 Actionscript 中,Class Method 只能访问 Class Methods 和 Class 属性。

这在 Objective-C 中也没有什么不同(因为没有别的意义),所以:

Class方法GameResultAll如何访问Instance方法initFromPlist

仅通过有效实例。

为什么[self init]调用方法而不是[self super]从类方法创建实例。

因为后者可能是语法错误?阅读基本的 Objective-C 教程。

于 2013-07-19T06:14:42.730 回答