Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-8010] Can an extension override (replace) a method or not? #50543

Open
mattneub opened this issue Jun 15, 2018 · 4 comments
Open

[SR-8010] Can an extension override (replace) a method or not? #50543

mattneub opened this issue Jun 15, 2018 · 4 comments
Labels
compiler The Swift compiler in itself documentation improvement

Comments

@mattneub
Copy link

mattneub commented Jun 15, 2018

Previous ID SR-8010
Radar None
Original Reporter @mattneub
Type Improvement
Environment

Xcode 10 beta 1

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Improvement, Documentation
Assignee None
Priority Medium

md5: 76050506b870038783f79d708432240c

Issue Description:

I'm confused about overrides in extensions (so maybe the bug is me). The language guide still says very clearly that "Extensions cannot override existing functionality". But that's clearly not true:

Framework MyCoolFramework:

open class MyClass {
    open func test() {
        print("test")
    }
    public init() {}
}

App target:

import UIKit
import MyCoolFramework
extension MyClass {
    func test() { // no "override"
        print("extension test")
    }
}
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let c = MyClass()
        c.test() // extension test
    }
}

So clearly we did override existing functionality, and we did it without having to say "override".

Another example. I can write:

extension UIButton {
    func setTitle(_ title: String?, for state: UIControl.State) {}
}

The compiler doesn't complain, and presto, I've totally broken this method, which is now a NOP throughout my code. I didn't have to say "override", so I had no idea I was doing this; and even if I know about it, I can't mend the problem, because the extension won't let me call `super` (well, it will, but it thinks `super` is UIControl, not UIButton).

Is this intentional, and if so, what's the intention?

(Note that this is a different issue from the question of whether I can extend a class and then subclass to override the extended functionality within the subclass.)

@belkadan
Copy link
Contributor

belkadan commented Jun 15, 2018

Yes and no. Or maybe no and yes.

In your first example, you haven't overridden test. Any existing code that's out there calling test will still be calling the original implementation. What you've done is add an overload for test.

In the second example, however, you're dealing with an Objective-C class. Methods in Objective-C are called by selector, which means that extensions can stomp on existing implementations. (This is a big problem when the "existing implementations" aren't public, which is why we chose a different approach for pure Swift methods.)

This probably does deserve better documentation. @natecook1000, where should that go?

@mattneub
Copy link
Author

mattneub commented Jun 15, 2018

An overload with the same signature? How does that work? If that were true, I would expect to be able to call either of them at will. How would I do that? And what does "out there" mean?

@belkadan
Copy link
Contributor

belkadan commented Jun 18, 2018

"out there" = "compiled without importing your app module" (so, any code that's in the framework).

It's a longstanding hole in the language that we don't have a way to say, e.g. c.MyCoolFramework::test() vs. c.MyApp::test() like we do for top-level values. Right now I believe the compiler resolves the ambiguity by always preferring the current module over other modules, but if you try in a unit test, for example, you should see the ambiguity you expect.

This feature in general, though, is important for Swift frameworks eventually being part of the SDK, so that when Apple (or someone) adds a new method to a class, it doesn't break your built apps. It's a place where Swift can do better than Objective-C.

@mattneub
Copy link
Author

mattneub commented Jun 18, 2018

It would appear, then, that I've accidentally duplicated https://bugs.swift.org/browse/SR-3228. Sorry about that.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler The Swift compiler in itself documentation improvement
Projects
None yet
Development

No branches or pull requests

2 participants