第5回(10/30) オブジェクトを作ってみよう ・Ruby の設計のうまさを体感しよう ☆ 分数クラス □□□ 演習:分数クラスを作ろう。□□□ ● ステップ1 ・分数クラスは Fraction という名前にする。 ・Fractionは、分子の数と分母の数を格納するためにインスタンス変数 @num と @den を持つ。 ・Fractionのインスタンスを作るとき、分子と分母の数が与えられるものとする。 たとえば、n = Fraction.new(1,2) とすると、変数 n が2分の1を表すようになる。 ・@numと@denは、クラス外から読み書きできるように、アクセサを作る。 ・分母と分子の数は、整数値またはFloat値が入るものとする。正負の符号、および、約分は、まだ考慮しない。 ⇒ prac0501.rb ● ステップ2 ・Float値を返す to_f、整数値を返す to_i、文字列を返す to_s を追加せよ。 たとえば、to_i は小数点以下を切り捨てる。n.to_s とすると、"1/2" を返す。これで、print n が有効になる。 ⇒ prac0502.rb ● ステップ3 ・分数同士のかけ算メソッド mult を作る。計算結果は、新しい分数インスタンスに格納し、それを return する。 ⇒ prac0503.rb ● ステップ4 ・分数.mult(整数) や 分数.mult(Float) ができるように mult を拡張する。 ヒント(1): def mult(n) もし n が Fraction のインスタンスであるならば、 ステップ3の方法で計算する そうではなく、n が Integer または Floatのインスタンスであるならば、 分子 と n をかけ算する。 分母は、かけられる数の分母と一致させる。 そうでなければ、 自身を小数に変換して、n とかけ算をする。 end ヒント(2): メソッドの引数が分数か整数か判定するには、kind_of? を使う。 ・分数/分数をinitializeメソッドで扱えるように変更する。たとえば、分母が1/2, 分子が 1/3 のとき、2/3 とする。 ⇒ prac0504.rb ● ステップ5 ・メソッド名の mult を止めて、演算子 * を使うように変更する。 ヒント: def * (引数) の形で宣言すればよい。 ⇒ prac0505.rb ● ステップ6 ・整数 x 分数 や Float x 分数ができるように拡張する。 ヒント(3):Ruby のうまいところ! Ruby では、ステップ3のヒント(1)のように、演算の引数をあらかじめ調べる約束になっている。未知の型を計算する場合には、自身を、未知の型のクラスの持つ型変換のメソッドにより変換させ、計算してもらうようになっている。 具体的に、「2 * 分数f」の計算過程は、 (1) 整数クラスの * メソッドで処理が始まる。 (2) 引数が分数であり、整数クラスから見れば、それは未知のクラスである。 (3) 自身(整数の2)を、分数fの型変換メソッドに送り、型を変換してもらう。 x,y = 分数f.coerce(2) (誤) (4) この結果、x に 分数fの値、y に分数型に変換された自身2の値が入る。 (正) (4) この結果、x に 分数型に変換された自身2の値、y に分数fの値が入る。 (5) y と x のかけ算をする。 (6) y が分数型なので、分数のかけ算メソッドで処理される。 ヒント(4):型変換のメソッド coerce {コウスと読む} http://rubycentral.com/book/ref_c_numeric.html#Numeric.coerce ・要するに、分数クラスに coerce メソッドを追加する。 ⇒ prac0506.rb ● ステップ7 ・ユークリッドの互除法のフローチャートを参照し、約分のメソッド reduce! を作る。 ・reduce! メソッド内で、分母の値が負にならないように変換せよ。 ・initialize、および演算子 * に reduce! の呼出しを追加する。 ⇒ prac0507.rb ● ステップ8 ・比較モジュール Comparable を有効にしたい。そのためには、演算子「<=>」が働かなければならない。 「<=>」の仕様を調べて、Fraction クラスに追加せよ。 ・n1 = Fraction.new(1,2) のとき、n1.between?(0,1) が true になるか? ・数クラス Numeric を継承するとどうなるか? ⇒ prac0508.rb ● ステップ9 ・残りの四則演算、+、-、/ を作れ。 ⇒ prac0509.rb ■ 宿題: (1) ステップ9まで作成し、以下のようにして実行結果を記録し印刷せよ。 (2) 授業時間でどこまで進んだかステップ番号を書け。(参考) (3) オブジェクト指向プログラミングの感想文を書け。(参考) 実行結果の記録方法 (1) 「prac0509.rb」を置いているディレクトリに移動する。 (2) 「emacs」を起動する。 (3) 「Escキー」を押し、「x」を押し、「shell」と入力し「リターン」を押す。 すると、emacs 上に kterm と同様のシェル・コンソールが表示される。 「ls」としてディレクトリを表示する。 (4) 「irb」を実行する。 (5) 「load "prac0509.rb"」を実行する。 (6) 「x = Fraction.new(1,2)」を実行する。 (7) 「y = Fraction.new(1,3)」を実行する。 (8) 「z = ( x + y ) * 2」を実行する。 (9) 「puts z」を実行する。 (10)「exit 」を実行する。 (11)「Controlキー」を押しながら「x」を押し、「Controlキー」を押しながら「w」を押す。 すると、ウインドウの最下行に、「Write file: ~何とかかんとか」と表示される。 (12)「kekka.txt」と入力し「リターン」を押す。 (14) もう一度「exit」を実行する。 すると、「Process shell finished」と表示される。 (15)「Controlキー」を押しながら「x」を押し、「Controlキー」を押しながら「c」を押す。 (16) kterm 上から kekka.txt を印刷する。 −−− ユークリッドの互除法のフローチャート −−−