==
演算子(Equatable
から)を基本クラスに実装しようとしています。そのサブクラスはSwift 3。すべてのクラスのみが使用されます。 in Swiftなので、NSObject
またはNSCopying
プロトコルを使用したくありません。
私は基本クラスとサブクラスから始めました:
class Base {
var x : Int
}
class Subclass : Base {
var y : String
}
ここで、Equatable
と==
演算子をBase
に追加したいと思いました。簡単そうです。ドキュメントから==
オペレーター署名をコピーします。
class Base : Equatable {
var x : Int
static func == (lhs: Base, rhs: Base) -> Bool {
return lhs.x == rhs.x
}
}
ここまでは順調ですね。サブクラスについて:
class Subclass : Base {
static override func == (lhs: Base, rhs: Base) -> Bool {
return true
}
}
しかし、これはエラーになります:
演算子関数は「最終的な」演算子関数をオーバーライドします
OK。いくつかの調査(まだ学習中Swift 3)の後、typeメソッドをオーバーライドできることを示すためにstatic
をclass
に置き換えることができることを学びました。
そこで、static
でclass
をBase
に変更しようとしています。
class Base : Equatable {
var x : Int
class func == (lhs: Base, rhs: Base) -> Bool {
return lhs.x == rhs.x
}
}
しかし、それは新しいエラーになります:
非最終クラス 'Base'で宣言された演算子 '=='は 'final'でなければなりません
うーん。これは、本来よりもはるかに複雑です。
Equatable
プロトコルと==
演算子を基本クラスとサブクラスに適切に実装するにはどうすればよいですか?
たくさんの研究と試行錯誤の末、私はついに実用的な解決策を思いつきました。最初のステップは、==
演算子をクラス内からグローバルスコープに移動することでした。これにより、static
とfinal
に関するエラーが修正されました。
基本クラスの場合、これは次のようになります。
func == (lhs: Base, rhs: Base) -> Bool {
return lhs.x == rhs.x
}
class Base : Equatable {
var x : Int
}
そしてサブクラスの場合:
func == (lhs: Subclass, rhs: Subclass) -> Bool {
return true
}
class Subclass : Base {
var y : String
}
残っているのは、サブクラスの==
演算子から基本クラスの==
演算子を呼び出す方法を理解することだけです。これは私を最終的な解決策に導きました:
func == (lhs: Subclass, rhs: Subclass) -> Bool {
if lhs.y == rhs.y {
if lhs as Base == rhs as Base {
return true
}
}
return false
}
その最初のif
ステートメントは、基本クラスの==
演算子の呼び出しになります。
最終的な解決策:
Base.Swift:
func == (lhs: Base, rhs: Base) -> Bool {
return lhs.x == rhs.x
}
class Base : Equatable {
var x : Int
}
Subclass.Swift:
func == (lhs: Subclass, rhs: Subclass) -> Bool {
if lhs.y == rhs.y {
if lhs as Base == rhs as Base {
return true
}
}
return false
}
class Subclass : Base {
var y : String
}
他の答えに続いて、私はこれを思いついた:
class Base : Equatable {
var x : Int
static func == (lhs: Base, rhs: Base) -> Bool {
return lhs.x == rhs.x
}
}
class Subclass : Base {
var y : String
static func == (lhs: Subclass, rhs: Subclass) -> Bool {
return lhs.y == rhs.y && (lhs as Base) == (rhs as Base)
}
}
rmaddyの答え に続いて、私は平等をテストするためのガードアプローチを思いつきました:
static func ==(lhs: Base, rhs: Base) -> Bool {
// ensure class properties match
guard lhs.x == rhs.x else {
return false
}
return true
}
static func ==(lhs: Subclass, rhs: Subclass) -> Bool {
// ensure base class properties match
guard lhs as Base == rhs as Base else {
return false
}
// ensure class properties match
guard lhs.y == rhs.y else {
return false
}
return true
}
`` `