Optionalのオーバーライドの挙動の検証
概要
もし親が Int で 子が Int? ならオーバライドできるので、
法則が乱れてるね、という話です
ということで今回の検証としてはOptionalのオーバーライドの挙動、
Arrayのオーバーライドの挙動を確認していきます
Optionalのオーバーライドの挙動
親クラスがIntのケース
親クラスのIntの場合は不自然なくサブクラス側としても
Int以外を指定するとエラーになる
// MARK: - // MARK: Int -> XXX class ReturnInt { var value: Int { return 0 } } class Subclass_ReturnIntFromInt: ReturnInt { override var value: Int { return 0 } } class Subclass_ReturnOpIntFromInt: ReturnInt { override var value: Int? { return 0 // -> note: attempt to override property here } } class Subclass_ReturnOpOpIntFromInt: ReturnInt { override var value: Int?? { return 0 // -> note: attempt to override property here } }
親クラスがOptional<Int>のケース
今回問題となってるケース、discordでも話題になってた通り親クラスのOptional
Optional
// MARK: - // MARK: Int? -> XXX class ReturnOpInt { var value: Int? { return nil } } class Subclass_ReturnIntFromOpInt: ReturnOpInt { override var value: Int { return 0 } } class Subclass_ReturnOpIntFromOpInt: ReturnOpInt { override var value: Int? { return 0 } } class Subclass_ReturnOpOpIntFromOpInt: ReturnOpInt { override var value: Int?? { return 0 // -> note: attempt to override property here } }
親クラスがOptional<Optional<Int>>のケース
// MARK: - // MARK: Int?? -> XXX class ReturnOpOpInt { var value: Int?? { return nil } } class Subclass_ReturnIntFromOpOpInt: ReturnOpOpInt { override var value: Int { return 0 // -> note: attempt to override property here } } class Subclass_ReturnOpIntFromOpOpInt: ReturnOpOpInt { override var value: Int? { return 0 // -> note: attempt to override property here } } class Subclass_ReturnOpOpIntFromOpOpInt: ReturnOpOpInt { override var value: Int?? { return 0 } }
結果
つまりOptionalのオーバーライドの挙動としてはこうなる、
見事にOptional<Int>の場合にIntもOptional<Int>も許容するという挙動なので
法則が乱れてると言えそう
親クラス | サブクラス Int |
サブクラス Optional<Int> |
サブクラス Optional<Optional<Int>> |
---|---|---|---|
Int | ○ | × | × |
Optional<Int> | ○ | ○ | × |
Optional<Optional<Int>> | × | × | ○ |
後日談
実はすでにこの問題の対応は行なっているらしくtarunonさんがプルリクを出してる
Array+Optionalのオーバーライドの挙動
WIP