私は Swift で iOS アプリケーションに取り組んできました (その多くは Objective-C から移動されています)。Core Data を使用しており、拡張機能を使用して、モデルから自動生成されたクラスに機能を追加しようとしています。私が Objective-C ですぐに実行したことの 1 つは、クラス A のカテゴリにメソッドを追加し、(A から派生した) クラス B のカテゴリでそのメソッドをオーバーライドすることでした。Swift でも同じことをしたいと思っていました。
しばらくの間、プロジェクトに次のコードがありました (これは 1 つの例にすぎません)。この機能はまだ使用していませんが、コンパイラはこのコードをコンパイルするのに問題なく動作しました。
// From CellType.swift -- NOTE: Imports from Foundation and CoreData
@objc(CellType)
class CellType: NSManagedObject {
@NSManaged var maxUses: NSNumber
@NSManaged var useCount: NSNumber
// Other properties removed for brevity
}
// From SwitchCellType.swift -- NOTE: Imports from Foundation and CoreData
@objc(SwitchCellType)
class SwitchCellType: CellType {
@NSManaged var targetCellXIndex: NSNumber
@NSManaged var targetCellYIndex: NSNumber
@NSManaged var targetCellType: CellType
// Other properties removed for brevity
}
// From CellTypeLogic.swift -- NOTE: Imports from Foundation and CoreData
extension CellType
{
var typeLabel : String { get { return "Empty"; } }
func isEqualToType(otherCellType : CellType) -> Bool
{
return (self.typeLabel == otherCellType.typeLabel &&
self.maxUses.isEqualToNumber(otherCellType.maxUses) &&
self.useCount.isEqualToNumber(otherCellType.useCount));
}
// Code removed for brevity
}
// From SwitchCellTypeLogic.swift -- NOTE: Imports from Foundation and CoreData
extension SwitchCellType // YES, this compiles with the overrides!
{
override var typeLabel : String { get { return "Switch"; } }
override func isEqualToType(otherCellType : CellType) -> Bool
{
var answer = false;
if let otherSwitchCellType = otherCellType as? SwitchCellType
{
answer = super.isEqualToType(otherCellType) &&
self.targetCellXIndex.isEqualToNumber(otherSwitchCellType.targetCellXIndex) &&
self.targetCellYIndex.isEqualToNumber(otherSwitchCellType.targetCellYIndex) &&
self.targetCellType.isEqualToType(otherSwitchCellType.targetCellType);
}
return answer;
}
// Code removed for brevity
}
うまくいけば、親切なSwiftの専門家が私の問題をすでに見ていますが、私がそれを見つけた方法は次のとおりです。最近、組み込み型ではないパラメーターや戻り値を持つメソッドを使用して同様の機能を追加しようとしましたが、これを取得し始めましたエラー: 拡張機能の宣言はまだオーバーライドできません。
この問題を調査するために、問題なくコンパイルできると考えて、swift ファイルの 1 つに以下を追加しました。
class A
{
}
class B : A
{
}
extension A
{
var y : String { get { return "YinA"; } }
}
extension B
{
override var y : String { get { return "YinB"; } } // Compiler error (see below) -- What??
}
驚いたことに、同じコンパイラ エラーが発生しました (拡張機能の宣言はまだオーバーライドできません)。何?しかし、私はそのパターンをコンパイラエラーなしですでに数回使用しました。
質問: まず、拡張機能のオーバーライドに関して、ある場合には機能するはずであるが他の場合には機能しないという特定の規則はありますか? 2 つ目 (さらに当惑させられること) は、なぜ Swift コンパイラがそれほど一貫性を欠いているように見えるのでしょうか? ここで何が欠けていますか?Swift への信頼を取り戻すのを手伝ってください。
アップデート:
Martin R の正解に記載されているように、(1) NSObject から派生したクラスのみを含み、(2) inout を使用しない限り、現在のバージョンの Swift (Xcode 6.1 経由の 1.1) のメソッドをオーバーライドできるようです。修飾子。以下にいくつかの例を示します。
class A : NSObject { }
class B : A { }
class SubNSObject : NSObject {}
class NotSubbed {}
enum SomeEnum { case c1, c2; }
extension A
{
var y : String { get { return "YinA"; } }
func f() -> A { return A(); }
func g(val: SubNSObject, test: Bool = false) { }
func h(val: NotSubbed, test: Bool = false) { }
func j(val: SomeEnum) { }
func k(val: SubNSObject, inout test: Bool) { }
}
extension B
{
// THESE OVERIDES DO COMPILE:
override var y : String { get { return "YinB"; } }
override func f() -> A { return A(); }
override func g(val: SubNSObject, test: Bool) { }
// THESE OVERIDES DO NOT COMPILE:
//override func h(val: NotSubbed, test: Bool = false) { }
//override func j(val: SomeEnum) { }
//override func k(val: SubNSObject, inout test: Bool) { }
}