web-dev-qa-db-ja.com

Swift 'open'キーワードと拡張機能のオーバーライド可能なメソッド/プロパティ?

Swift 3.0( Swiftの「open」キーワードとは )にopenキーワードが導入されました。

注:NSObject派生クラスまたは_@objc_属性のメソッド/プロパティの拡張機能に限定されます。

publicが壊れたように、拡張acrossモジュール/フレームワークでclasspublic)メソッド/プロパティを宣言して使用したコードが壊れましたモジュールの定義外で「オーバーライド可能」を意味しなくなりました。

例:

_public extension UIManagedDocument {

    public class func primaryDocumentName() -> String {
        return "Document"
    }

    public class func primaryStoreURL() -> URL {
        let documentsURL = FileManager.default.userDocumentsURL
        return URL(fileURLWithPath: self.primaryDocumentName(), isDirectory: false, relativeTo: documentsURL)
    }

    public class func primaryModelName() -> String? {
        return "Model"
    }

}
_
  • 元の提案( SE-0117 )はサブクラス化に焦点を当てており、拡張については言及していません。
  • 現在、拡張機能はopenキーワードをサポートしていません(_open extension NSObject_およびopen func Method()を記述できません)

質問:拡張機能が提供するメソッド/プロパティ全体モジュール/フレームワークをオーバーライドできる回避策はありますか?

10
Nocross

私が間違っていない限り、拡張機能でopenキーワードを省略した場合は、canフレームワークで拡張メソッドをpublicとして宣言します。宣言:

extension UIManagedDocument {

    open class func primaryDocumentName() -> String {
        return "Document"
    }
    // ...
}

次に(NSObjectサブクラスまたは@objcメンバーの場合)、メインアプリケーション(または任意のモジュール)のカスタムサブクラスのメソッドをオーバーライドできます。

class MyManagedDocument: UIManagedDocument {

    override class func primaryDocumentName() -> String {
        return "MyDocument"
    }
    // ...
}
8
Martin R
  • 'プロトコル指向'-宣言プロトコル必要なメソッド/プロパティを使用して、拡張機能をリファクタリングしてプロトコルに準拠します。
  • 'Traditional'-必要なメソッド/プロパティを使用して中間(抽象)サブクラスを実装します。

プロトコルの例:

protocol PrimaryDocument {
    static func primaryDocumentName() -> String

    static func primaryStoreURL() -> URL

    static func primaryModelName() -> String?
}

extension UIManagedDocument : PrimaryDocument {

    open class func primaryDocumentName() -> String {
        return "Document"
    }

    open class func primaryStoreURL() -> URL {
        let documentsURL = FileManager.default.userDocumentsURL
        return URL(fileURLWithPath: self.primaryDocumentName(), isDirectory: false, relativeTo: documentsURL)
    }

    open class func primaryModelName() -> String? {
        return "Model"
    }

}
3
Nocross