C言語のいわゆる「K&R」本を読んでいたら、構造体というのはオブジェクト指向によく似ていると思った。ので、この本の第六章のスクリプト(p.155-159)を、Ruby で表現してみる。
少なくともここでは、C言語の構造体が完全に Ruby の OOP に移植できている。
#点を表すクラス class Point def initialize(x = 0, y = 0) @x = x @y = y end attr_accessor :x, :y def addpoint(p) #2点p1, p2の座標を足して、Pointを返す @x += p.x @y += p.y self end alias + addpoint end #2点をインスタンス変数にもつクラス。向かい合った2点によって表される長方形とも考えられる class Rect def initialize @pt1 = Point.new @pt2 = Point.new end attr_accessor :pt1, :pt2 def cannonrect #レシーバーの値を「標準形式」(下を参照)に直して返す temp = Rect.new temp.pt1.x = getmin(@pt1.x, @pt2.x) temp.pt1.y = getmin(@pt1.y, @pt2.y) temp.pt2.x = getmax(@pt1.x, @pt2.x) temp.pt2.y = getmax(@pt1.y, @pt2.y) return temp end end #以下、トップレベルでのメソッドの定義 def ptinrect(q, r) return (q.x >= r.pt1.x && q.x < r.pt2.x && #pt1の各座標はpt2の各座標より小さくなければならない q.y >= r.pt1.y && q.y < r.pt2.y) #(標準形式)。pがrの中ならtrue、そうでなければfalse end def getmin(x, y) return (x < y) ? x : y end def getmax(x, y) return (x > y) ? x : y end
例を挙げてみる。点pt と原点との距離を求める。
pt = Point(300, 400).new p Math.sqrt(pt.x ** 2 + pt.y ** 2) #=> 500.0
2点の中点(あるいは、長方形の真ん中の点)を求める。
screen = Rect.new screen.pt1 = Point.new(100, 0) screen.pt2 = Point.new(200, 100) middle = Point.new((screen.pt1.x + screen.pt2.x) / 2, (screen.pt1.y + screen.pt2.y) / 2) p middle #=> #<Point:*** @x=150, @y=50>
2つの位置ベクトルの和を求める。
v1 = Point.new(20, 30) v2 = Point.new(50, 90) p v1.addpoint(v2) #=> #<Point:*** @70, @y=120> p v1 + v2 #=> #<Point:*** @70, @y=120> + は addpoint のエイリアス
点q が長方形r の内部にあるか。
r = Rect.new r.pt1 = Point.new(20, 30) r.pt2 = Point.new(100, 200) q = Point.new(50, 70) p ptinrect(q, r) #=> true q = Point.new(50, 20) p ptinrect(q, r) #=> false
長方形r を定義する 2点を、「標準形式」に直す。
r = Rect.new r.pt1 = Point.new(100, 200) r.pt2 = Point.new(10, 20) p r.cannonrect #=> #<Rect:*** @pt1=#<Point:*** @x=10, @y=20>, @pt2=#<Point:*** @x=100, @y=200>>