From: gotoken@... (GOTO Kentaro) Date: 1999-11-27T10:19:22+09:00 Subject: [ruby-list:18973] Re: initializer polymorphism? ごとけんです In message "[ruby-list:18953] Re: initializer polymorphism?" on 99/11/26, Takeyuki Watadani writes: >渡谷です。 >話はそれますが、instance_evalを使うといつでもどこでも誰でも >カプセル化を容易に破壊できるんですね。クラスに定義を追加した >りメソッドを削除したりもできるし… てわけで、instance_evalで書き直してみました。最後につけます。 >#本物のRubyプログラマは紳士だってことですね。きっと。 >#あ、淑女でももちろんいいです。 ^^; Rubyの場合、裏口から楽屋に入れるわけですね。逆にいえば楽屋に は裏口からしか入れない。そういう気分になってしまうし、そう書 くようにひそかに矯正されてしまいます。こうして、しばらくRuby を使っていると「どのように書くか」に集中してしまうようになる。 危険な言語です ^^;;; # See also [ruby-list:16616] >class 三角形 >... >end >ってやると >class/module name must be CONSTANT >って怒られてしまいますね。やっぱり大文字じゃないって判定にな >るのか… 日本語文字の識別子は小文字で始まるものとみなされます。 -- gotoken #!/usr/local/bin/ruby class Triangle include Math def initialize @hen1 = @hen2 = @hen3 = nil end attr_reader :hen1, :hen2, :hen3 Prototype = Triangle::new class << self undef new def newInstanceFrom3hen(hen1, hen2, hen3) Prototype.clone.instance_eval { @hen1, @hen2, @hen3 = hen1, hen2, hen3 self # `instance_eval' returns the last value } end def newInstanceFrom2hen1kaku(hen1, hen2, kaku) Prototype.clone.instance_eval{ hen3 = sqrt(hen1**2 + hen2**2 - 2*hen1*hen2*cos(kaku)) @hen1, @hen2, @hen3 = hen1, hen2, hen3 self } end end end include Math p Triangle.newInstanceFrom3hen(5, 5, 5) p Triangle.newInstanceFrom2hen1kaku(5, 5, PI/3) # omake: congruent relations version :-) class Triangle include Math attr_reader :side0, :side1, :side2 def initialize @side0 = @side1 = @side2 = nil end Prototype = Triangle::new Triangle.instance_eval{ undef new } class UniqueTriangles < Hash; end # implimataion goes blow ThreeSides = UniqueTriangles.new(nil) TwoSidesOneAngle = UniqueTriangles.new(nil) def TwoSidesOneAngle.sides_for(side0, side1, angle) [side0, side1, sqrt(side0**2 + side1**2 - 2*side0*side1*cos(angle))] end class UniqueTriangles < Hash # implemetation here TrianglePool = {} protected :[]= def [](a0,a1,a2) s = sides_for(a0,a1,a2) c = permutation(*s).sort{|i,j| i.collect{|a| [a.type.name, a]} <=> j.collect{|a| [a.type.name, a]} } TrianglePool[c[0]] or begin res = TrianglePool[c[0]] = generate(*c[0]) c.each{|i| self[i] = res} res end end def sides_for(a0, a1, a2) # default interpretation of self[args] [a0, a1, a2] end private def generate(a0,a1,a2) Prototype.clone.instance_eval { @side0, @side1, @side2 = a0, a1, a2 self } end def permutation(a0,a1,a2) [[a0,a1,a2], [a1,a2,a0], [a2,a0,a1], [a2,a1,a0], [a0,a2,a1], [a1,a0,a2]] end end end if __FILE__ == $0 include Math S3 = Triangle::ThreeSides S2A1 = Triangle::TwoSidesOneAngle p S3[5,5,5] p S2A1[5,5,PI/3] p S3[1,2,3] == S3[2,3,1] #=> true p S2A1[1,5,PI/3] == S2A1[5,1,PI/3] #=> true p S3[1,1,1] == S3[1,1,1.0] #=> false (type mismatch) p S2A1[5,5,PI/3] == S3[5,5,5.0] #=> false (numerical error) end