I try only to put the necessary things (stored properties, initializers) in my class definitions and move everything else into my own extension , sort of like extension for each logical block that I would group with // MARK: as well.
For a UIView subclass, for example, I get an extension for layout related materials, one for subscribing and handling events, etc. In these extensions, I inevitably have to override some UIKit methods, for example. layoutSubviews . I have never noticed any problems with this approach - until today.
Take this class hierarchy, for example:
public class C: NSObject { public func method() { print("C") } } public class B: C { } extension B { override public func method() { print("B") } } public class A: B { } extension A { override public func method() { print("A") } } (A() as A).method() (A() as B).method() (A() as C).method()
The output signal is ABC . It makes little sense to me. I read about static messages about protocol extensions, but this is not a protocol. This is a regular class, and I expect method calls to be dynamically dispatched at runtime. Obviously, a call to C should be at least dynamically sent and produce C ?
If I remove the inheritance from NSObject and make C root class, the compiler complains about saying declarations in extensions cannot override yet , which I already read about. But how to make NSObject as a root class change things?
Moving both overrides into their class declaration creates AAA , as expected, only B produces ABB , only moving A calls CBC , the last of which makes absolutely no sense to me: even the one that is statically printed on A gives A -output more!
Adding the dynamic keyword to a definition or override seems to give me the desired behavior "from this point in the class hierarchy down" ...
Let's change our example to something less constructed that actually made me post this question:
public class B: UIView { } extension B { override public func layoutSubviews() { print("B") } } public class A: B { } extension A { override public func layoutSubviews() { print("A") } } (A() as A).layoutSubviews() (A() as B).layoutSubviews() (A() as UIView).layoutSubviews()
Now we get ABA . Here I cannot make UIView layoutSubviews dynamic in any way.
Moving both overrides into their class declaration again returns us AAA , only A or only B still gets us ABA . dynamic solves my problems again.
In theory, I could add dynamic to all the override I've ever done, but feel like I'm doing something else wrong.
Is it really wrong to use extension to group code like me?