お世話になっております。 A.中村です。 On Thu, 3 Nov 2005 13:56:13 +0900 IWAOKA Masahiro様 iwaoka / tuat.jac-net.com wrote: > オブジェクトを主体として考えるならば、第三者(Cat)によって戦わさ > れてる(上の例)というよりは、"mike" が "tama" と戦う(例えば > mike.fight(tama))の方が自然だと思います。baby の例も同様。 mike.fight_with(tama) #「hogehogeと戦う」が英語ではFight WITH hogehogeだったかどうかは #自信が無いですが… というメソッドは存在していいと想いますが、 それとは別問題として、 「両者を対等に捉えたい」っていう要望もまた アリだとは想います。 主体といっても、現実は、 これが主体だ!と言い切れるケースばかりじゃないので、 ちょっと微妙なんですよねー。 なんか世間にはMultipleDispatchとかいって 複数のオブジェクトの「組み合わせ」に対して メソッドを呼ぶ(メッセージを送信する)ということが できる言語もあるらしいです。 #Lisp系とかで見かけるらしいですが、 #かくいう俺も触ったことはまだ無いので伝聞です… そういう言語だと、 対等に捉えたfightも自然に記述できるんでしょうね。 が、まあ今主流の言語にはその機能は無いようです。 MultipleDispatchなやり方だと、もしかすると、 闘技場とか、戦う動機とか、戦う種目とか、もまた 組み合わせるオブジェクトたちの1つとして参加する のかなあ… さてRuby。 個人的には、ArrayとかEnumerableに ちょいとfightメソッドをつけちゃうといいかな という気がしています。 Arrayに恒久的につけるのは不味いでしょうけど、 まあ1つのプログラムの中の話ですし、 かたいこと言わずに(^^; …てゆーか、Enumerableと同じ立場の (つまりeachとかを持つクラスにincludeしてもらうような) moduleを1つ作ればいいんですかね。 #EnumerableとかArrayとかにmix-inしてくださーい module Fighters #要素がfight_with(敵)を受け付けることを期待してまーす def fight self.each{|me| (self.to_a - [me]).each{|enemy| me.fight_with(enemy) } } end end module Fighter def initialize(name) @name=name end attr :name def fight_with(you) puts "#{self.name}曰く「#{you.name}よ、俺はお前を倒す!!」" #相手次第で戦い方を替える、というコードが何もありませんが…(^^; #あと動機や種目の概念も無いなあ。うーん… end end class Cat; include Fighter; end class Dog; include Fighter; end [ Cat.new("mike"), Cat.new("tama"), Dog.new("pochi"), ].extend(Fighters).fight sh-2.04 % ruby -v fighters.rb ruby 1.8.2 (2005-02-01) [i386-mswin32] mike曰く「tamaよ、俺はお前を倒す!!」 mike曰く「pochiよ、俺はお前を倒す!!」 tama曰く「mikeよ、俺はお前を倒す!!」 tama曰く「pochiよ、俺はお前を倒す!!」 pochi曰く「mikeよ、俺はお前を倒す!!」 pochi曰く「tamaよ、俺はお前を倒す!!」 まあようするに 「不細工」な部分はライブラリ(?)の中に隠しちゃえ という話です。 あと、extendでヤリ逃げするってのは結構好きかも。 module自体はライブラリとして作り置きできるんで クラスじゃなくインスタンスに対してちょっかい出しても 全体としてはあまり汚くならない(きがする)し。