オープンクラスとVisitor

RDToolを弄ってたら久々にRubyでVisitorパターンを見た。 起源の古いライブラリではVisitorも見るけど、最近のRubyライブラリではあまり多くない気がする。

そう言えばVisitorパターンは GoF には、「継承階層への追加を困難にするかわりに振る舞いの追加を容易にする」と書いてある。

継承階層のノードに応じて様々な挙動をするのは本来は多態性の役目だ。ところが、Visitorパターンではメソッドのシグネチャ自体を変えることによりノードを区別する。ノードを追加するにはVisitorの提供するインターフェースに新しいメソッドを追加しなくてはならないので、追加は困難となる。

一方、違う振る舞いをしたければ違うVisitorを渡せばよい。通常は違う振る舞いをしたかったら継承階層に新たにメソッドを追加しなくてはならなくて、これが再コンパイルをもたらすような言語では巨大な階層にメソッドを追加することは困難極まる。Visitorパターンでは、実際に振る舞うのはvisitorオブジェクトなのでこれを差し替えればよい。Strategy的に、実行時にvisitorを変えることすら可能だ。

なのだけれども、Rubyの場合オープンクラスが当たり前であって、継承階層に振る舞いを追加するコストがそもそも高くない。だから、Visitorは「ノード追加のコストが高くなる」というデメリットばかりが目立って活躍する場所が少なくなるんだな。

復習でした。

追記

parser系ライブラリは例外的に、やっぱりvisitorをよく見かける。そうか、この手のライブラリは継承階層自体がAPIの一部だから、階層への追加が困難であっても困らない。そして、継承階層への振る舞いの追加は可能な限り楽にしたい。「これこれに気をつけてメソッドを追加してね」という訳にはいかないんだ。

一方、もっと内部的な用途で継承階層を渡り歩く場合には、振る舞いを追加する人は継承階層の内部実装についてもよく知っていることを期待でき、この場合はメソッドを追加する方が楽なんだろう。すると、使うべき所にvisitorが残って、今までvisitorは大げさすぎた場所では使われなくなった、ということか。