web-dev-qa-db-ja.com

拡張機能からの宣言は、Swift 4でまだオーバーライドできません

最近、コードをSwift 4に移行しました。私が直面している問題がありますextensions、つまり:

拡張機能からの宣言はまだオーバーライドできません

この問題に関する複数の投稿を既に読んでいます。ただし、それらのいずれも、以下に説明するシナリオを楽しませません。

_class BaseCell: UITableViewCell
{
    //Some code here...
}

extension BaseCell
{
    func isValid() -> String?
    {
        //Some code here...
    }
}

class SampleCell: BaseCell
{
    //Some code here...

    override func isValid() -> String? //ERROR..!!!
    {
        //Some code here...
    }
}
_

Appleによると、

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

しかし、上記のシナリオでは、拡張機能でisValid()メソッドをオーバーライドしていません。 SampleCellクラス定義自体でオーバーライドされます。それでも、エラーが発生しています。

13
PGDev

しかし、上記のシナリオでは、拡張機能でメソッドisValid()をオーバーライドしていません。

isValidextensionで宣言されます。

このエラーは、関数がこのように宣言されている場合、オーバーライドできないと言っています。

このステートメントは、拡張機能から拡張機能からの両方に有効です。

11
Tamás Sengel

プロトコルを@objcする限り、拡張機能からの宣言をオーバーライドできます。 In Swift 4.2:

class BaseClass {}
class SubclassOfBaseClass: BaseClass {}

@objc protocol IsValidable {
    func isValid() -> Bool
}

extension BaseClass: IsValidable {
    func isValid() -> Bool { return false }
}

extension SubclassOfBaseClass {
    override func isValid() -> Bool { return !super.isValid() }
}

BaseClass().isValid()           // -> false
SubclassOfBaseClass().isValid() // -> true
6
Adam Preble

Swift 3では、拡張機能がObjective-Cから派生したクラスの場合、拡張機能をオーバーライドできました( http://blog.flaviocaetano.com/post/this-is-how-to-override-extension-methods / )、しかしSwift 4.では不可能だと思います。もちろん、次のようなことができます:

protocol Validity {
    func isValid() -> String?
}

class BaseCell: UITableViewCell, Validity {

}

extension Validity
{
    func isValid() -> String? {
        return "false"
    }
}

class SampleCell: BaseCell {

    func isValid() -> String? {
        return "true"
    }
}


let base = BaseCell()
base.isValid() // prints false

let sample = SampleCell()
sample.isValid() // prints true
5
Puneet Sharma

これは一目瞭然だと思います。 宣言[〜#〜] from [〜#〜]拡張機能はまだオーバーライドできません

overrideクラス自体ではなく、extensionBaseCell内で宣言された関数func isValid() -> String?BaseCellしようとしています。

拡張機能内で宣言されたものをオーバーライドできないことを明確に言っています。

お役に立てば幸いです。

3
Tarun Tyagi

私もSwift 3コードの巨大な遺産を持っていたので、この古いトリックを使用して望みを達成したため、Swift 4に移動してこれらのエラーを取得し始めたとき、私は多少苦しみました。 。恐れないで、解決策があります。

このエラーは、Swift 4がクラスをコンパイルする方法と、Objective-Cのクラスと関数を処理する新しい方法に関係しています。 Swift 3の下で、クラスがNSObjectから派生している場合、そのクラスのすべての変数と関数は、Objective-Cの動的な命名規則と検索規則を使用します。このアプローチは、コードを最適化し、コードのパフォーマンスとサイズを改善するSwiftの機能を阻害しました。

これらのペナルティを克服するために、Swift 4では、@objcで明示的にタグ付けされた変数と関数のみがObjective-C処理を取得し、他のすべては標準のSwift規則を使用します:したがってエラー。

この知識を備えた問題の解決策は、オーバーライドする拡張機能の関数に@objcのタグを付け、次に子クラスで関数をオーバーライドすることです。ただし、@objcタグは、実行時にコードが呼び出されるようにします。

[〜#〜] warning [〜#〜]これはちょっとした落とし穴です。@objcoverrideに含めるのを忘れても、コンパイラは文句を言いません。ただし、コードには動的ルックアップがないため、実行時に呼び出されることはありません。

したがって、コードは次のようになります。

class BaseCell: UITableViewCell {
    //Some code here...
}

extension BaseCell {
    @objc func isValid() -> String? {
        //Some code here...
    }
}

class SampleCell: BaseCell {
    //Some code here...

    @objc override func isValid() -> String? {
        //Some code here...
    }
}
1
pbc

Swiftでは無効ですが、Objective-Cでは無効です。したがって、メソッドシグネチャで許可されている場合(objcで禁止されている構造はありません)、@objc func myMethod()を宣言して、Swiftで自由にオーバーライドできます。

0
Rafael Nobre