2

假设你有一个 UIView 子类。您定义了一个初始化方法“myInitWithFrame: ... andWhatNot:...”。您知道您永远不会使用从 UIView 继承的 init 方法,并且您的自定义 init 方法会执行一些重要的自定义初始化,因此您希望强制客户端类永远不要使用继承的 initWithFrame 方法。

是否可以隐藏从 UIView 继承的标准 initWithFrame 方法?

4

3 回答 3

20

实际上,您可以获得有关在子类上调用方法的编译时警告。使用__attribute((deprecated))属性。如果您希望人们使用-initWithPizza:而不是-initWithFrame:,请执行以下操作:

@interface MyView : UIView
- (id)initWithPizza:(MyPizza *)pizza;
@end

@interface MyView (Deprecations)
- (id)initWithFrame:(CGRect)frame __attribute((deprecated("Use initWithPizza: instead")));
@end

-initWithFrame:声明放在单独的类别中是必要的,以避免 Xcode 抱怨您在标头中声明了该方法但没有实现它。既然你只是从超类继承它,那很好;您根本不必实施它。但是,如果您想实现它以引发异常,或者-initWithPizza:使用默认参数调用 to,那很好。

当然,-initWithFrame:如果 UIKit 已经这样做了,这不会阻止 UIKit 调用。但如果你能保证这不会发生,那你就没事。

于 2013-05-31T22:18:38.500 回答
7

实际上,您可以使用子类进行限制。您可以覆盖要在子类.h文件中阻止的任何方法。您可以initWithFrame通过将以下内容放入.h文件中来使其不可用。

- (id) initWithFrame:(CGRect) frame __attribute__((unavailable("message")));

这将使initWithFrame:使用您的子类的任何人都无法使用该方法。

要保留其他代码形式调用此方法,您可以通过将其放入.m文件中来进一步限制。

- (id) initWithFrame:(CGRect) frame
{
    return nil;     
}
于 2013-05-31T22:09:13.840 回答
3

不,您不能阻止子类的用户调用超类的方法。你可以覆盖它们并在里面抛出一个异常,但这只会产生一个损坏的子类。

请记住,继承作为“is a”扩展工作,也就是说,您的子类的实例应该在任何不知道这个特定子类但知道它的超类的上下文中正常运行。只有在对您的子类有明确了解的地方,您才能从添加额外的初始化和其他方法中受益。

例如,UIKit 不知道您的子类。因此,如果您想让您的 UIView 子类可从 NIB 使用,您需要使用将由 NIB 加载系统调用的初始化方法,即initWithCoder:. 你可以简单地在里面调用你自己的初始化方法initWithCoder:。但是,如果您想将任何其他参数传递给 init 方法,则必须提供一种在初始化后配置它们的方法。

于 2013-05-31T16:23:52.960 回答