Swift dispatch to overridden methods in subclass extensions

前端 未结 1 1140
[愿得一人]
[愿得一人] 2021-01-01 21:54

overriding method signatures in extensions seems to produce unpredictable results in certain cases. The following example demonstrates two different results with a similar p

相关标签:
1条回答
  • 2021-01-01 22:13

    The surprise here is that the compiler permits the override in the extension. This doesn't compile:

    class A {
        func doThing() {
            print("dothing super class")
        }
    }
    class B: A {
    }
    extension B {
        override func doThing() { // error: declarations in extensions cannot override yet
            print("dothing sub class")
            super.doThing()
        }
    }
    

    In your example, it appears that the compiler gives you a pass because A derives from NSObject — presumably in order to allow this class to interact with Objective-C. This does compile:

    class A : NSObject {
        func doThing() {
            print("dothing super class")
        }
    }
    class B: A {
    }
    extension B {
        override func doThing() {
            print("dothing sub class")
            super.doThing()
        }
    }
    

    My guess is that the fact you're allowed to do this override at all is itself possibly a bug. The docs say:

    Extensions can add new functionality to a type, but they cannot override existing functionality.

    And overriding is nowhere listed as one of the things an extension can do. So it seems like this should not compile. However, perhaps this is permitted deliberately for compatibility with Objective-C, as I said before. Either way, we are then exploring an edge case, and you have very nicely elicited its edginess.

    In particular, the preceding code still doesn't cause dynamic dispatch to become operational. That's why you either have to declare doThing as dynamic, as suggested by @jtbandes, or put it in the actual class rather than the extension — if you want polymorphism to operate. Thus, this works the way you expect:

    class A : NSObject {
        dynamic func doThing() {
            print("dothing super class")
        }
    }
    class B: A {
    }
    extension B {
        override func doThing() {
            print("dothing sub class")
            super.doThing()
        }
    }
    

    And so does this:

    class A : NSObject {
        func doThing() {
            print("dothing super class")
        }
    }
    class B: A {
        override func doThing() {
            print("dothing sub class")
            super.doThing()
        }
    }
    

    My conclusion would be: Very nice example; submit it to Apple as a possible bug; and Don't Do That. Do your overriding in the class, not in the extension.

    0 讨论(0)
提交回复
热议问题