3

我有两个类,Class1 和 Class2,第二个继承自第一个。我需要重写 Class1 的 -update 方法来实现我的目标。继承方法中-update方法的更改是在代码中间进行的,所以我不能使用[超级更新]。这就是为什么我需要将原始方法从父类复制粘贴到继承类。此方法使用父级的私有方法,因此当我尝试进行覆盖时,我收到有关缺少私有方法的警告,因为 Class2 仅导入 Class1.h。为了澄清,这里是代码:

类1.h:

@interface Class1 : NSObject
-(void) update;
@end

类1.m:

@interface Class1 (Private)
-(void) private1;
-(void) private2;
@end

@implementation Class1

-(void) update
{
    [self private1];
    [self private2];
}

-(void) private1
{
    // some code
}

-(void) private2
{
    // another code
}

@end

类2.h:

@interface Class2 : Class1
-(void) update;
@end

类2.m:

@implementation Class2

-(void) update
{
    [self private1]; // warning here
    // do my own stuff between private methods, that is the reason of inheritance
    [self private2]; // warning too
}

@end

此外,Class1 不属于我的所有权,它是来自开源库(准确地说是 Cocos3D)的一个,所以我无法更改它(这就是我进行继承的原因)。

问题是:如何删除警告?我能看到的唯一解决方案是将私有方法的签名复制到 Class2,但这似乎是一个肮脏的把戏。或者,如果有人指出的不是如何删除警告,而是如何更好地实现我改变方法的目标,那将是完美的。

4

4 回答 4

7

无需 swizzling、performSelector: 或任何其他运行时漏洞。

只需移动或复制这个:

@interface Class1 (Private)
-(void) private1;
-(void) private2;
@end

到子类的 .m 文件的开头。

通常,当尝试实现@protected方法范围之类的东西时,此类声明将在头文件中,Class1_Private.h并且该头文件将设置为privateXcode 中的角色。

正如其他人所指出的,通过这种机制公开私有方法有点危险。鉴于 Cocos2D 是开源的,这种危险在一定程度上得到了缓解,或者您总是可以直接对其进行修改。当然,这样做意味着您实际上拥有一个分支,维护成本很高。

如果这是其他开发人员可能会做的事情,我建议向 Cocos2D 提交一个错误,要求为子类化目的公开这些方法。

于 2013-03-07T16:18:12.043 回答
2

Apple 这样做的方式是使任何可以在子类中被覆盖的方法都公开,但记录不应直接调用它们而只能被覆盖的事实。Apple 代码的文档(通常)是全面的,并且经常被引用,所以这是可行的。当然,典型的第三方代码没有很好的文档记录,文档也不太可能被阅读......

另一种解决方案:我经常创建一个名为“MyClass+SubclassMethods.h”的第二个头文件,并公开声明子类可覆盖,但在其中的一个类别中声明为私有方法。在基类和子类用户的源文件中,这不会被导入,因此这些方法(有效地)保持私有。在基类的子类中,我导入“MyClass+SubclassMethods.h”以允许我覆盖/调用这些方法。这不是一个完美的解决方案,但如果没有 Objective-C 中“受保护”方法的概念,我不确定是否有更好的解决方案。

于 2013-03-07T16:08:56.200 回答
0

鉴于 Class1 无法修改,另一个响应中建议的类别是一个很好的解决方案。如果可以对源进行调整,则在单独的头文件中声明的类扩展和在 Class1 实现和 Class2 实现文件中的#imported 将是一种方式,因为这样您不仅可以共享私有方法,还可以共享实例变量以这种方式标记@public 或@protected。从这里了解更多关于类扩展的信息:

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html

简而言之,类扩展有点像类别(有时称为私有类别),但它只能在实现其扩展的类的同一编译单元中声明,并且可以声明(和自动合成)属性和实例变量。Xcode 中包含一个用于创建类扩展的源代码模板(见下文。)

Xcode 中的类扩展创建

于 2013-03-07T23:10:54.637 回答
-2

您应该能够使用类别来扩展您的原始类并尝试方法调配以实现您想要的行为来解决这个问题。

于 2013-03-07T13:56:56.420 回答