• 検索結果がありません。

レコードとオブジェクト

N/A
N/A
Protected

Academic year: 2021

シェア "レコードとオブジェクト"

Copied!
33
0
0

読み込み中.... (全文を見る)

全文

(1)
(2)

レコード

class Point attr_accessor("x", "y") end … point.rb インスタンス変数の宣言

(3)

irb(main):004:0> load("point .rb") => true irb(main):005:0> p = Point.new() => #<Point:0x40332080> irb(main):006:0> p.x = 3 => 3 irb(main):007:0> p.y = 4 => 4 irb(main):008:0> p => #<Point:0 x40332080 @y=4, @x=3> オブジェクト (Pointクラスの インスタンス) インスタンス変数への代入 インスタンス変数への代入

(4)

irb(main):013:0> p.y => 4 irb(main):014:0> sqrt(p.x**2 + p.y**2) => 5.0

• Rubyでは,レコードもオブジェクトの一種

• レコードのクラスは,インスタンス変数の宣言

のみから成る

インスタンス変数の参照

(5)

… def point_make(u,v) p = Point.new() p.x = u p.y = v p end … オブジェクト(への参照)を返す point.rb

(6)

… def point_scale(p,s) point_make(p.x*s, p.y*s) end def point_add(p,q) point_make(p.x+q.x, p.y+q.y) end … point.rb

(7)

def point_interpolate(p,q,t)

point_add(point_scale(p,1-t), point_scale(q,t)) end

def point_draw(p,a)

if 0 <= p.y+0.5 && p.y+0.5 < a.length() && 0 <= p.x+0.5 && p.x+0.5 < a[0].length() a[p.y+0.5][p.x+0.5]=1 end end point.rb 配列aの縦の長さ 配列aの横の長さ Rubyの配列の添え字が実数でも いいことを利用している 0.5は四捨五入をするため

(8)

load("./max.rb") load("./abs.rb")

def line_draw(p0,p1,a)

n=max(abs(p1.x - p0.x), abs(p1.y - p0.y)) for i in 0..n

point_draw(point_interpolate(p0,p1,i*1.0/n), a) end

end

(9)

def bezier_draw(p0,c,p1,a) n = 10 prev = p0 for i in 1..n t = i*1.0/n q0 = point_interpolate(p0, c, t) q1 = point_interpolate(c, p1, t) r = point_interpolate(q0, q1, t) line_draw(prev, r, a) prev = r end end bezier.rb

(10)

練習

• max.rb と abs.rb を用意し、point.rb、line.rb、

bezier.rb をロード。make2d も定義。

• 以下を順に isrb のもとで実行せよ。

p0 = point_make(10,10)

p1 = point_make(90,90)

c = point_make(10,90)

a = make2d(100,100)

bezier_draw(p0,c,p1,a)

show(a)

(11)

もっと,レコード

class Line attr_accessor("p0", "p1") end class Bezier attr_accessor("p0", "c", "p1") end

(12)

レコードの意義

• 一まとまりの複数のデータを表す変数が1個ですむ – Pointの場合,x座標とy座標をまとめて扱える – Lineの場合,始点と終点をまとめて扱える • 4つの座標をまとめて扱えている – Bezierの場合,始点と終点,第3点をまとめて扱える • 6つの座標をまとめて扱えている • このようなデータのまとまりを値として扱える – 関数の値として返すことができる • 4つの座標を返すことは通常の関数では難しい – 内部のデータがどうなっているかを知らなくても使うことが できる • もし,Pointの座標系が極座標系だったとしても,関数の使い方に変 更を加える必要がない

(13)

しかし,レコードのままだと…

• クラス(レコードの種類)ごとに操作を定義

Pointクラス Lineクラス Bezierクラス

point_draw line_draw bezier_draw

• これらが混在している場合,

if figureがPointクラスのオブジェクト point_draw(figure,a) else if figureがLineクラスのオブジェクト line_draw(figure,a) else if figureがBezierクラスのオブジェクト bezier_draw(figure,a)

(14)

オブジェクト指向では

• オブジェクト(ここではレコードのこと)に自分

に対する操作の仕方を覚えさせる

– Pointのレコードに,スカラー倍,ベクトル和などの 操作を覚えさせる – 自分の操作法を知っているレコードをオブジェクト と呼ぶ – それぞれのPointオブジェクトが操作法を抱え込 むのは大変なので,Pointオブジェクトを,Pointク ラスにまとめ,「親分」のPointクラスがPointオブ ジェクトの作り方や操作法を一括管理する

(15)

レコードからオブジェクトへ

オブジェクト 内部データ構造 + 処理手続き レコードの変数 にアクセスするのと 同じ形での質問や 動作の依頼 それに対する応答 隠蔽されている(カプセル化) 実は,オブジェクトのクラスがこれ らを知っている 個々のオブジェクトは自分の具体 的な値を知っている メッセージとも言う

(16)

クラス

class Point attr_accessor("x", "y") def initialize(u,v) self.x = u self.y = v end def scale(s) Point.new(self.x * s, self.y * s) end def add(q)

Point.new(self.x + q.x, self.y + q.y) end end scaleメソッド 初期化メソッド 自分自身の x @x でもよい oo-point.rb 自分の操作法を メソッドと呼ぶ

(17)

irb(main):005:0> p = Point .new(3,4) => #<Point:0x7ffa3ed8 @x=3, @y=4> irb(main):006:0> p.x => 3 irb(main):007:0> q = p.scale(2) => #<Point:0x7ffa3e84 @x=6, @y=8> irb(main):008:0> p.add(q) => #<Point:0x7ff9b0f8 @x=9, @y=12> irb(main):009:0> p.add(q).scale(0.5) => #<Point:0x7ff94ca8 @x=4.5, @y=6.0> 初期化メソッドの引数 新しいオブジェクト 新しいオブジェクト 新しい オブジェクト

(18)

Pointクラスに以下のメソッドを追加。 def move(x,y) self.x = x self.y = y end irb(main):002:0> p = Point.new(3,4) => #<Point:0x7ffa32bc @y=4, @x=3> irb(main):003:0> p.move(4,6) => 6 irb(main):004:0> p => #<Point:0x7ffa32bc @y=6, @x=4>

(19)

class Line attr_accessor("p0", "p1") def initialize(q,r) self.p0 = q self.p1 = r end def draw(a) n = max(abs(self.p1.x - self.p0.x), abs(self.p1.y - self.p0.y)) for i in 0..n p = self.p0.interpolate(self.p1, i*1.0/n) p.draw(a) end end … oo-line.rb

(20)

多相性

def drawall(elements,a)

for i in 0..elements.length()-1

elements[i].draw(a)

end

a

end

elements[i] のクラスが何であれ, そのdrawメソッドが呼ばれる drawall.rb

(21)

… def drawmoon() p0=Point.new(0,85) p2=Point.new(99,85) f=[Line.new(p0,p2), Bezier.new(p0,Point.new(50,60),p2), Circle.new(Point.new(66,20),20)] a=make2d(100,100) drawall(f,a) show(a) end drawall.rb

(22)

練習

• Pointクラスにdrawメソッドを追加せよ。

– すなわち、oo-point.rb のPointクラスの中に、 def draw(a) … end を追加。 – point.rb の point_draw を参考に。

• interpolateメソッドを追加(次のスライド参照)。

• drawmoon() を実行せよ

– 必要なクラスのファイルをロードする。 – oo-circle.rb は萩谷のページから。

(23)

def interpolate(q,t)

self.scale(1-t).add(q.scale(t))

end

もしくは

def interpolate(q,t)

scale(1-t).add(q.scale(t))

end

(24)

進捗状況の確認

1. drawmoon が動いた時点で、投票してくださ

い。

2. drawメソッドを追加したが、drawmoon が動

かない。

3. drawメソッドができない。

(25)

提出

• drawメソッドもしくは oo-point.rb 全体を

is-komaba@lyon.is.s.u-tokyo.ac.jp

に送ってください。

(26)

継承

class Bezier < Line

attr_accessor("p0", "c", "p1") def initialize(q,r,s) super(q,s) self.c = r end … def turn(theta) super(theta) self.c = self.c.rotate(theta) end end Lineクラスを継承 Lineクラスの初期化メソッドを呼び出す Lineクラスのturnメソッドを呼び出す oo-bezier.rb

(27)
(28)
(29)
(30)
(31)

オブジェクト,クラス,インスタンス変数,メソッド

• オブジェクト – コンピュータのなかで「もの」に対応する"もの" • クラス – 同じようなオブジェクトをまとめたもの – プログラミングでは先にクラスを定義しておき,必要に応じ てクラスに属するオブジェクトを生成する – 生成したオブジェクトを,クラスのインスタンスという • インスタンス変数 – オブジェクトなかでデータを表す要素 – レコードではフィールド,「もの」の視点では属性に対応 • インスタンスメソッド – オブジェクトの操作を行うためのメソッド メッセージのやり取りはメソッドの呼び出しで代用 メッセージの内容は引数に対応

(32)

カプセル化,継承,多相性

• カプセル化 – 「もの」を表すデータとメソッドをまとめ,決められたインス タンスメソッドを通してのみインスタンス変数にアクセスを させ,インスタンス変数に直接触らせないこと • 継承 – 他のクラスのインスタンス変数やメソッドを受け継いで新 しいクラスを作ること – 新しいクラスをサブクラス,元のクラスをスーパークラスと 呼ぶ • 多相性 – 同じ名前のインスタンスメソッドを呼び出しても,適用され たオブジェクトによって異なるメソッドを呼び出すこと – 実行時にメソッドを探す動的結合で実現する

(33)

オブジェクト指向プログラミング言語

• オブジェクト指向の要素をどのように言語としてまと めるかは,プログラム言語設計者の腕のみせどころ であり,いろいろなバリエーションがある • ここではRubyでの書き方を紹介する • 一つの言語で書き方を覚えておけば,他のバリエー ションも短時間で使いこなすことができるようになる だろう • バリエーションについては第10章で少し紹介する

参照

関連したドキュメント

1.レコードセレクターをクリック 2.別のレコードにカーソルを移動 3.ウィンドウを閉じる 4.データベースを閉じる 5.Access を終了する.

ところで,このテクストには,「真理を作品のうちへもたらすこと(daslnsaWakPBrinWl

の点を 明 らか にす るに は処 理 後の 細菌 内DNA合... に存 在す る

11) 青木利晃 , 片山卓也 : オブジェクト指向方法論 のための形式的モデル , 日本ソフトウェア科学会 学会誌 コンピュータソフトウェア

不変量 意味論 何らかの構造を保存する関手を与えること..

LLVM から Haskell への変換は、各 LLVM 命令をそれと 同等な処理を行う Haskell のプログラムに変換することに より、実現される。

ライセンス管理画面とは、ご契約いただいている内容の確認や変更などの手続きがオンラインでできるシステムです。利用者の

(4) 現地参加者からの質問は、従来通り講演会場内設置のマイクを使用した音声による質問となり ます。WEB 参加者からの質問は、Zoom