トップ «前の日記(2017-12-09) 最新 次の日記(2017-12-11)» 編集

Cocoa練習帳

iOS/iPhone/iPad/watchOS/tvOS/MacOSX/Android プログラミング, Objective-C, Cocoa, Swiftなど

2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|
2020|01|02|03|04|05|06|07|08|09|10|11|12|
2021|01|02|03|04|05|06|07|08|09|10|11|12|
2022|01|02|03|04|05|06|07|08|09|10|11|12|
2023|01|02|03|04|05|06|07|08|09|10|11|12|
2024|01|02|03|04|05|

2017-12-10 [マサカリ]やはりお前らの継承は間違っている。

ほぼ同じコードが複数の箇所に存在している場合、それを共通化すること自体は推奨されることだと思う。ただ、共通化の手法としてクラスの継承を使い、基底クラスに共通コードを実装する場合は手を動かす前に考えた方がいいと思う。オブジェクト指向という名前からも関連があるものがクラス化されるものだと思うが、共通化目的の場合、関連がないものも継承関係に含めてしまっていないかという事を。

これから失敗の事例を説明していく。

共通コードを〜Baseという名前で規定クラスで実装する。

class MyBase {
    func aaa() {
        bbb();
    }
    
    func bbb() {
    }
}
 
class Xxx : MyBase {
    override bbb() {
    }
}
 
class Yyy : MyBase {
    override bbb() {
    }
}

派生クラスの異なる部分をbbb()メソッドで実装する。この瞬間はうまくいっているように見える。

派生クラスXxxとYyyは関係が薄い場合、異なる方向で仕様が変わったとする。そして、上記のコードで都合が悪くなったとする。そんな時、以下のような修正をしてしまわないか?

class MyBase {
    func aaa() {
        if n == abc {
            bbb(2);
        }
        else {
            bbb(1);
        }
    }
    
    func bbb(kind: Int) {
    }
}
 
class Xxx : MyBase {
    override bbb(kind: Int) {
    }
}
 
class Yyy : MyBase {
    override bbb(kind: Int) {
    }
}

基底クラスに派生クラスを考慮したコードが入ってしまう。

この問題を解消するために、基底クラスと派生クラスの間に中間の基底クラスを作成してしまう。そしてくクラスの数の大爆発と派生クラスのコードを読んでも意味が分からない。

この問題の回避は難しい。指摘しても、コードは共通化するものだ。逆にこの手の事をやってしまう人は、積極的にコード構成に意見する場合があるし。

こんな事を投稿してしまった場、マサカリがブーメランとなって自分のところに飛んでこない事を祈っている。

_ 【Cocoa練習帳】

http://www.bitz.co.jp/weblog/
http://ameblo.jp/bitz/(ミラー・サイト)
Qiita

トップ «前の日記(2017-12-09) 最新 次の日記(2017-12-11)» 編集