【问题标题】:How Class Method can access Instance Method ?类方法如何访问实例方法?
【发布时间】:2013-07-19 06:11:54
【问题描述】:

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

但在 Objective C 中,

  1. 类方法gameResultAll如何访问实例方法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;
}

【问题讨论】:

  • @H2CO3 lololol 我只是想说
  • 对不起,我是第一次使用。我更新了。

标签: objective-c


【解决方案1】:

你问:

Class方法gameResultAll如何访问Instance MethodinitFromPlist

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

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

然后你继续问:

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

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

想象一下这个场景:

  • 在未来的某个日期,您将继承 GameResult,例如ArcadeGameResult;

  • 您为ArcadeGameResult 实现了一个init 方法,该方法初始化了该子类独有的一些属性;和

  • 您碰巧像这样初始化ArcadeGameResult 实例:

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

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

底线,除非您调用的方法是完全相同相同的方法签名,否则调用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,并且此实例方法仍然有效。如果使用前一种构造,则子类方法不会被someInstanceMethod 调用。

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

【讨论】:

  • 太棒了。感谢您的详细解释。
【解决方案2】:

在 Actionscript 中类方法只能访问类方法和类属性。

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

类方法GameResultAll如何访问实例方法initFromPlist

仅通过有效实例。

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

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

【讨论】:

    猜你喜欢
    • 2015-07-09
    • 1970-01-01
    • 2021-06-03
    • 2014-01-26
    • 2017-05-12
    • 2013-09-08
    • 2016-05-20
    • 1970-01-01
    • 2012-12-18
    相关资源
    最近更新 更多