final, private, @objc, dynamic — how do they affect dispatch?
The idea
Modifiers move a method along the scale "static → vtable → objc_msgSend". The more calls are static, the more inlining and the faster the code; dynamism is needed for overriding, KVO and swizzling.
import Foundation
class Base: NSObject {
func a() {} // vtable
final func b() {} // static: cannot be overridden
private func c() {} // static: override impossible
@objc func d() {} // Swift: vtable, Obj-C: objc_msgSend
@objc dynamic func e() {} // always objc_msgSend (KVO, swizzling)
dynamic func f() {} // native dynamic replacement, no Obj-C
}
extension Base {
@objc func g() {} // extensions have no vtable → objc_msgSend
}
The rest of this answer, with code and interview follow-ups, is in the DevPrep app.
Read the full answer in DevPrep