如果我有课:
class Spaceship<FuelType> {
function prepareForLiftoff() throws {
//Start the countdown!
}
}
我最初假设我可以通过添加扩展来覆盖prepareForLiftoff
而不进行子类化:
extension Spaceship where FuelType: CollectionType {
func prepareForLiftoff() throws {}
}
此代码无法编译,错误显示函数的invalid redeclaration
,这是有道理的。
我的问题是:无论如何都要覆盖特定类的功能?换句话说,我可以在某些条件下替换功能,例如FuelType: CollectionType
上面的示例。如果没有,是否有任何其他解决方法或方法来实现该行为(可能声明另一个协议,idk)
现在我想起来了,我不得不说这是不可能的,因为阻止某人覆盖任何标准库函数的是什么?
答案 0 :(得分:20)
答案 1 :(得分:1)
您可以尝试调配,而不是覆盖。例如,以下代码允许您运行自己的viewWillAppear
。 Swift 3
:
extension UIViewController {
open override class func initialize() {
// make sure this isn't a subclass
guard self === UIViewController.self else { return }
DispatchQueue.once(token: "viewWillAppear") {
let originalSelector = #selector(self.viewWillAppear(_:))
let swizzledSelector = #selector(self.proj_viewWillAppear1(animated:))
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
func proj_viewWillAppear1(animated: Bool) {
self.proj_viewWillAppear1(animated: animated)
let viewControllerName = NSStringFromClass(type(of: self))
print("viewWillAppear: \(viewControllerName)")
}
}
更新20170621
public extension DispatchQueue {
private static var _onceTracker = [String]()
public class func once(file: String = #file, function: String = #function, line: Int = #line, block:(Void)->Void) {
let token = file + ":" + function + ":" + String(line)
once(token: token, block: block)
}
public class func once(token: String, block:(Void)->Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if _onceTracker.contains(token) {
return
}
_onceTracker.append(token)
block()
}
}