Optionalのオーバーライドの挙動の検証

概要

moaible-swift-memo.hateblo.jp

もし親が 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のみならず、Intを指定しても許容されている

// 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さんがプルリクを出してる

github.com

Array+Optionalのオーバーライドの挙動

WIP