inheritance:限制而不是扩展?
假设你有一个UIView子类。 你定义一个init方法“myInitWithFrame:…和WhatNot:…”。 你知道你将不会使用从UIViewinheritance的init方法,你的自定义init方法会做一些重要的自定义初始化,所以你想强制客户端类永远不要使用inheritance的initWithFrame方法。
是否有可能隐藏从UIViewinheritance的标准initWithFrame方法?
实际上,你可以得到关于在子类上调用方法的编译时警告。 使用__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抱怨你在头中声明了该方法,但没有实现它。 既然你只是从超类inheritance它,那很好; 你根本不需要实现它。 但是,如果你想实现它来抛出一个exception,或者调用通过-initWithPizza:
默认参数,那很好。
当然,这不会阻止UIKit调用-initWithFrame:
如果它已经这样做了。 但是,如果你能保证不会发生,那么你很好。
其实,你可以用一个子类来限制。 您可以覆盖要在您的子类的.h
文件中阻止的任何方法。 您可以通过将以下内容放在.h
文件中来使initWithFrame
不可用。
- (id) initWithFrame:(CGRect) frame __attribute__((unavailable("message")));
这将使任何人使用你的子类initWithFrame:
方法不可用。
为了让其他代码forms调用这个方法,你可以进一步限制在.m
文件中。
- (id) initWithFrame:(CGRect) frame { return nil; }
不可以。您不能阻止您的子类的用户调用超类的方法。 你可以覆盖它们并抛出一个exception,但这只会产生一个破碎的子类。
请记住,inheritance是一个“是”的扩展,也就是说,你的子类的实例应该在任何不知道这个特定子类但是知道它的超类的上下文中正常运行。 只有在对你的子类有明确的知识的地方,你才能从添加额外的初始化和其他方法中受益。
例如,UIKit不知道你的子类。 所以如果你想让你的UIView子类可以从NIB中获得,你需要使用由NIB加载系统调用的初始化方法,即initWithCoder:
你可以简单地在initWithCoder:
调用你自己的初始化方法initWithCoder:
但是,如果有任何其他参数想要传递给init方法,则必须在初始化之后提供一种configuration方法。