Private Interface イディオム

基底クラスのメソッドを派生クラスで隠す手法について調べてみました。

この手法は合法なのか?

まずは C++ FAQ Lite に以下の記述を見つけました。

[21.1] Should I hide member functions that were public in my base class?

Never, never, never do this. Never. Never!

Attempting to hide (eliminate, revoke, privatize) inherited public member functions is an all-too-common design error. It usually stems from muddy thinking.

http://www.parashift.com/c++-faq-lite/proper-inheritance.html#faq-21.1

完全否定ですね。でも、具体的な理由を書かずに「ありがちな設計ミス」と断定するのはどうなのかなぁ。まあいいか。次。

comp.lang.c++.moderated から「Virtual method is public in base class and private in inherited one」というスレッド。賛否両論あって面白いのですが、インタフェース継承やデザインパターンに馴染んでいる人ほど、肯定的に受け取っているようです。

その中でも我が意を得たり、というコメントがこれ。

Wouldn't you agree that you should minimize the public interface of a class?
In other words, it is a good idea to have as few methods in a class's public
interface as possible.

Given the above, if a virtual function is *always* going to be called via a
base class pointer then make the virtual function private in derived
classes.

An example would be the 'update' function in the Observer design pattern.

http://groups.google.co.jp/group/comp.lang.c++.moderated/msg/0aa12f98dc47cd5e?dmode=source

全くその通りですよ、うんうん。さらに、

The concept is about granting exclusive access to selective clients.
This is a standard idiom, and it has a name: Private Interface. You can
read about it at the same Object Mentor web site that offers the LSP
artcicle you are citing below.

http://groups.google.co.jp/group/comp.lang.c++.moderated/msg/7e486d664519b605?dmode=source

というコメントから、これが Private Interface イディオムだとわかったので、原典を探してみました。

http://www.objectmentor.com/resources/articles/privateInterface.pdf

動機のところなどは Buddy イディオムを考えた時と大体同じですね。C++Java による実装例が紹介されているのですが、C++ については非公開継承を使っているので、今となっては正しくない内容です。UML のクラス図は正しいのに惜しい。本来の意味での Private Interface を実装するならやはり、公開継承して多態性を確保するのが筋でしょう。

それから、この文書には Private Interface には多重継承を促進する効果がある、という指摘があります。実は密かに同じことを考えていたので、驚きつつも嬉しくなりました。実装ではなくインタフェースを継承することの本質を理解すると、多重継承も自然と受け入れることができますね。

まとめ

結局のところ、Private Interface は利用すべきなのか。

Private Interface を使っても、基底クラスを経由すれば簡単にコンパイラを出し抜くことができます。そういった意味では、悪意を持った侵入に対しては無力な、子供だましのテクニックかもしれません。でも、不要なインタフェースを隠して誤用を防ぐ姿勢は大切だし、品質を作り込む観点からも効果的です。Private Interface が必要なら、躊躇せずにどんどん使うべきでしょう。ただ、あまり期待しすぎてはいけない。

すっきりしたところで、開発も頑張ります。