web-dev-qa-db-ja.com

拡張機能の宣言は、Swift 4のエラーをまだ上書きできません

私には拡張子があります:

public extension UIWindow {
    override public func topMostController()->UIViewController? { ... }
}

しかし、私のtopMostControllerについては、次のエラーが表示されます。

Declarations in extensions cannot override yet error

Swift 3.1ではうまく機能しますが、Swift 4ではこのエラーが発生します。どうすれば修正できますか? Swift 4では何が変更されましたか?

58
J. Doe

基本実装を@objcにすると機能します。内部の詳細な説明については、 ハミッシュの答え を参照してください。

拡張機能で宣言されたメソッドをオーバーライドすることは、正しく行うには少し注意が必要です。 Objective-Cはこれをサポートしていますが、絶対に安全ではありません。 Swiftは、それを改善することを目指しています。提案はまだ完了していません。

利用可能な提案の現在のバージョン here

64
Sulthan

拡張機能は、新しい機能を型に追加できますが、既存の機能を上書きすることはできません。

拡張機能は、既存のクラス、構造、列挙、またはプロトコルタイプに新しい機能を追加します。これには、元のソースコードにアクセスできない型を拡張する機能が含まれます(遡及モデリングと呼ばれます)。

Swiftの拡張機能:

  • 計算されたインスタンスプロパティと計算された型プロパティを追加する
  • インスタンスメソッドとタイプメソッドを定義する
  • 新しい初期化子を提供する
  • 添え字を定義する
  • 新しいネストされた型を定義して使用する
  • 既存のタイプをプロトコルに準拠させる

Apple開発者ガイド

あなたがしようとしていることは、このコードによって行われたことに似ています:

class MyClass: UIWindow {
    func myFunc() {}
}

extension MyClass {
    override func myFunc() {}
}

注:override topMostController()を使用する場合は、UIWindowのサブクラスを作成します

12

Swift 5.0

実際、OPコードにはいくつかの問題があります。

  1. UIViewUIWindowのスーパークラス)にはメソッドtopMostController()がないため、オーバーライドできません。

  2. Apple 推奨しないextension内のoverride func

    拡張機能は、新しい機能を型に追加できますが、既存の機能を上書きすることはできません。

  3. それでも拡張機能をオーバーライドしたい場合は、2つの方法があります。

[A]親クラスで@objc dynamic funcを使用して関数をマークします。

class Vehicle {
    @objc dynamic func run() { /* do something */ }
}

class Car: Vehicle { }

extension Car {
    override func run() { /* do another thing */ }
}

[B]NSObjectの子孫である組み込みクラスの関数をオーバーライドします。

 extension UIWindow {
    // UIWindow is a descendant of NSObject, and its superclass UIView has this function then you can override
    override open func becomeFirstResponder() -> Bool {
        ...
        return super.becomeFirstResponder()
    }
 }
0
nahung89