親クラスのメソッドを隠す

id:siokoshou:20070901#p2、id:siokoshou:20070903 の補足やらなにやらをつらつらだらだらと。

反変

id:siokoshou:20070901#p2 で書いた例は、オブジェクト指向に詳しい方なら「それって反変」とピンと来たと思います。オブジェクト指向のややこしぃ話に「共変(covariant)と反変(contravariant)」ってのがあって、Method( string )/Method( object ) の例はその反変の例になっています。前回の答えのエントリでは、親のメソッドを隠してしまうことをわりと否定的なニュアンスで書きましたが、わざと便利に使うこともできます。だからこそコンパイラは警告も出さないんでしょう、たぶん。難しい話はよくわからないので檜山さんによる詳しい説明をドゾー。牛スキーにはたまらないお話です(^^;

あれ?この説明読むともしかしてこういう動きの言語のほうが普通なのかな…?
オブジェクト指向は便利に使えているうちは好きですが、こういうややこしぃお話は避けて通ってます、ハイ。MSDNライブラリを共変とか反変でキーワード検索するとデリゲートとジェネリックが引っかかって興味深いお話が載ってたりします。ほかに配列の共変性なんてのもあります。ちなみに共変のオーバーロードは特におもしろいことも何もなく、普通に使えます。
ところで、short/int の例は共変とか反変とか言うんでしょうか?継承関係はないけれど、暗黙の変換はあるという例でしたけど。共変と反変の詳しい定義がわかりません…。

オーバーロードか隠蔽か?

id:siokoshou:20070903 では注意してこれらの用語を使わなかったんですが、どっちなのかよくわからなかったからだったりします(まぁどっちでもいいんだけどw)。C# コンパイラにしてみればオーバーロードなんだろうけど、意味的には「隠蔽」ですよね。C# ではシグネチャが一致した隠蔽の場合はコンパイル時に警告が出るので、警告を消すには new 修飾子を付けますね。
先の2例ではコンパイラは何も言わないけど、親のメソッドが見えなくなるので隠蔽にあたると思うんですけどねぇ。コンパイラが警告出したほうが親切じゃね?とか思うのは過剰な期待でしょうか…。

FxCopで検出できるか?

FxCopは大げさだし、しょうもない警告をいっぱい出して重要な警告が埋もれてしまうので嫌いなんですが、まぁ使ってみました(lint もどきはいらないから、gcc -Wall もどきが欲しい!)。
string/object の例は検出できました。Design Rules/Do not hide base class methods ルールです。CA1061。でも、short/int の例は検出できず。
おそらく継承関係があれば検出できるけど、継承関係がなくて暗黙の変換による隠蔽の場合は検出できないんだと思います。そんなにいろいろ試したわけじゃないので、多分に推測を含みますが。

この事実は有名?

C#の仕様書は参考とか例が豊富ですが、JISの仕様書をざっと見た限りでは触れてなさげです。リッチャー本でも触れてなさげ。関係ないけど id:siokoshou:20070901#1 はリッチャー本におもいっきり書いてありました…。NULL チェックが不要なときの例はさすがに載ってなかったけど。
FxCop でも検出が中途半端だし、もしかして、あまり知られていないのかも?


わかっててわざと使うんだったらOKと思いますが、ついついこの落とし穴に落ちないためにはオーバーロードの濫用を控えるってのが有効な手というところでしょう。