投稿数 - 437, コメント - 52868, トラックバック - 156

オーバーライド可能なメソッドのないクラスはシールにすべきか

internal sealed

C++(普通の) では、仮想関数が存在する時は、デストラクタは仮想デストラクタにしなければならない。仮想関数が存在するという事は、そのクラスは基底クラスになる予定があるという事だからだ。

逆を返せば、仮想関数が存在しない時は、デストラクタは仮想デストラクタにする必要はない。(してはいけない?…ということではないと思う)

.NET 対応言語では、オーバーライド可能なメソッドが存在しない時は、そのクラスはシールにすべきなのだろうか。

私の考えは「とりあえずシールにしとけ」だ。

継承のメカニズムの利点は「拡張」というよりは「ポリモーフィック」に扱えるかどうか、だと思う。何か共通処理があるから基底クラスにしたりとか、拡張したいから何かから派生したりというよりは、さまざまな派生クラスを「同一のように(ポリモーフィック)」に扱いたい、というとき継承を使う。(もちろん前者達の意味でも使いたい時はあるが)

そう考えると、オーバーライド可能なメソッド(またはプロパティ)を持たないクラスは、継承予定がないという事になるので、そのクラスはシールにすべきかと悩む。シールにしなくても特筆すべき害悪(シールにすると若干パフォーマンスが良くなるというのはある)がないところが更に悩みに拍車をかける。

ところで、.NET で「オーバーライド可能なメソッドを持たないクラス」というのは作りにくい。というより、かなり意図して作らないといけない。理由は Object の存在だ。

ご存知の通り .NET 界では、如何なるクラスも Object の DNA を受け継いでいる。Object に存在するオーバーライド可能メソッドもその一つだ。

ToString() や Equals() をオーバーライドして、わざわざ sealed キーワードをつける人が何人いるだろうか。つまり、オーバーライド可能なメソッドが存在しないクラスというのはほぼ存在しないという事になる。

いや逆か?このクラスをシールにしたいという要求が存在するから、全てのメソッドはオーバーライド不可能になるのか?

…とここまで書いて、ちょうど中さんが似た投稿をしてる事に気付いた。


sealedクラス、NotInheritableクラスの効用

投稿日時 : 2006年3月13日 13:12

フィードバック

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

うーん、オーバライド可能なメソッドが有るとか無いとかより、
作り手が「そいつから導出して欲しくない」ならsealed
だと思うし、僕はそーします。
結果的に全メソッドがオーバライド不可。
つか、導出して欲しくないんだから当然なんだが。

2006/03/13 13:46 | επιστημη

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

コメントありがとうございます.

>うーん、オーバライド可能なメソッドが有るとか無いとかより、
>作り手が「そいつから導出して欲しくない」ならsealed
>だと思うし、僕はそーします。

 επιστημη さん的には「そいつから導出して欲しくないわけではない」けど「オーバーライド可能なメソッドがない」というのは,sealed なしでしょうか?
 私は,「そいつから導出して欲しくない」という明確な理由はないけれども,導出しても意味がない(オーバーライド可能なメソッドがない)というやつは sealed にしてしまいます.
 オーバーライド可能なメソッドがないから導出しても意味がないというのは乱暴すぎるのかもしれませんが.
2006/03/13 14:32 | 囚人

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

>「そいつから導出して欲しくないわけではない」けど「オーバーライド可能なメソッドがない」というのは,sealed なしでしょうか?

です(多分)。
「sealedでないと困る」んじゃなければnon-sealedですねぇ。

「ギョーザも食えるラーメン屋」を作りたいのに「ラーメン屋」のガンコ親父が「俺ぁラーメン一本でぃっ」ってsealedしちゃったら困るもん。

2006/03/13 14:48 | επιστημη

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

そうすべきかどうかについては置いといて、
Java の final 論争と同じく「眉唾もの」じゃないんですか?

私はどうしているか。
自作クラスのほとんどが NotInheritable になってます。
コントロール クラスの場合も基本は継承禁止です。

勝手に継承して勝手な実装されても困るので。
あ、グループ開発での話をかなり考慮しています。

クラス ライブラリ作成者に許可を得て初めて Inheritable にすると...
2006/03/13 15:08 | じゃんぬ

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

「眉唾もの」と言いますと? 何のどこらへんが疑わしいのかしら?

考え方の違いといってしまえばそれまで、ですかね。
僕は継承禁止にできない/多重継承アリアリな環境で育ってきたんで、「いぢり放題だけどいぢって転んでも泣きつくな」なんですよね ^^;

fixed@Java, sealed@.NET が要らない/欲しくない こたぁねぇです。 羨ましく思えることはよくあります。
2006/03/13 15:19 | επιστημη

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

このあたりの最適化って、アセンブリがロードされてから解決する問題なんだろうか。

上にもリンクあるけど、もう 1 回置いておく。
ttp://blogs.wankuma.com/naka/archive/2006/03/13/21816.aspx
2006/03/13 15:48 | じゃんぬ

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

ぁぁぁsealedだとちょびっと速いかも、が「眉唾もの」なのね。
実測を伴わない推測には心動かされはしませんですねぇ。
実測値が出たにしても0.2%速い、なんてんじゃつまんないし。
2006/03/13 15:56 | επιστημη

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

>「sealedでないと困る」んじゃなければnon-sealedですねぇ。

>僕は継承禁止にできない/多重継承アリアリな環境で育ってきたんで、「いぢり放題だけどいぢって転んでも泣きつくな」なんですよね ^^;
>fixed@Java, sealed@.NET が要らない/欲しくない こたぁねぇです。 羨ましく思えることはよくあります。

言われてみると,sealed でないと困るというシナリオが現実にはあまりないですね.
C++ では継承禁止を明示する場合は,「仮想でないデストラクタを用意」しかないんでしょうか.これを見逃して継承しちゃう人もいるんで,とりあえず仮想デストラクタにしとけ!になったり^^;
コンパイラが弾いてくれる sealed はすっばらスィ.


>このあたりの最適化って、アセンブリがロードされてから解決する問題なんだろうか

>実測を伴わない推測には心動かされはしませんですねぇ。

コメントありがとうございます.

異なった IL が吐かれると期待しましたが,どうやら IL レベルでの違いはないようですね.どういう風に最適化するのかは興味あり.
シールクラスにすべきかどうかの主軸は「パフォーマンス」より「クラスの意味」ですね.
2006/03/13 16:56 | 囚人

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

>C++(普通の) では,仮想関数が存在する時は,デストラクタは仮想デストラクタにしなければならない.

私は長いこと COM で遊んできたので、仮想デストラクタはあんまり使わない派です。
DLL のようなバイナリ形式のプラグインを考えると、インスタンス破棄も通常のメソッド呼出しと同じ形であってくれた方が嬉しいという理由です。

DLL 内で new されたオブジェクトを EXE 内で delete なんてのはまさに C++ 設計時の想定外に見えるというか。
アンマネージドな世界で COM は良い落としどころだと思いますし、そういう世界だと仮想デストラクタが適切とは言えない局面もあるように思います。

(GDI+ なんかは delete をメンバ関数としてオーバーロードしたりして色々がんばってますな。)
2006/03/13 18:31 | NyaRuRu

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

コメントありがとうございます。

>私は長いこと COM で遊んできたので、仮想デストラクタはあんまり使わない派です。

ほ~、なるほど。
私がこの世界に新規参入^^;してきたときは、既に「これからは.NETの時代だ。COM の時代は終わった」(そんな時代が本当に来るのかは別として)とか謳われていた時なので、COM の実装はほとんど分かりません^^;
ATL なんかよく判らんから、COM の仕組みをほじろうとしてそのまま放置…。

>アンマネージドな世界で COM は良い落としどころだと思いますし、そういう世界だと仮想デストラクタが適切とは言えない局面もあるように思います。

ふむふむ、なるほど。(よくわかんないですけど^^;)
私も COM で遊びたくなってきました。
2006/03/14 10:19 | 囚人

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

sealedにするとパフォーマンスがよくなるってのはC++/CLIの仕様書に書いてあります。
他にもちらほら。

Essential.NETを読めば継承リストをたどっていくなんてことをCLRがやっているので、多少のパフォーマンスアップを望めるだろうというのはなんとなくすとんと落ちます。
ただし0.2%とかってところってのは大当たりだと思います。

>僕は継承禁止にできない/多重継承アリアリな環境で育ってきたんで、「いぢり放題だけどいぢって転んでも泣きつくな」なんですよね ^^;

C++ってそういう意味でやはり組み立てていくものなんですよね。
組み立てさせたりしないものなんだと(^^;;

実装面で目が届く範囲を十分に意識しないと・・・

なので難しいんですよね。
2006/03/14 23:33 | 中博俊

# re: オーバーライド可能なメソッドのないクラスはシールにすべきか

どうしても継承して欲しくない「お客様は手を出すな」なら、
C++(に限らないけど)ではインタフェースとそれを実装したなにかを返すメソッドのみを利用者に公開するってーことになりますし。
# あるいはhandle-bodyイディオムで。

2006/03/15 13:35 | επιστημη

# SS品

ブランド写真店
最新の更新のブランドバッグコピー
┏─┓┏─┓┏─┓│郵送して
送ります││材料││ありませ
ん││材料│┗─┛┗─┛┗─
┛┗─┛◆---◆---◆---◆---◆---◆---◆---◆---◆---◆
◆※◆二つ折り、三つ折り、長財布◆※◆
◆※◆自動巻き、手巻き腕時計◆※◆
◆※◆バッグ、財布、腕時計◆※◆を得ています!!!
▲信用第一、高品質 安心 最低価格保証
★歓迎光臨★送料無料(日本全国)
2017/10/07 8:15 | ejfzyioqi@docomo.ne.jp

コメントの投稿

タイトル
名前
URL
コメント