10の練習問題をやってみよう(五日目)
新しくプログラミング言語を覚えたいときに行うべき10の練習問題
実際にやってみよう。
メソッドを定義するメソッドというものを作りたい。
def_push_nums 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
ってやったら
def push_0 @disp = @disp * 10 + 0 end def push_1 @disp = @disp * 10 + 1 end ...
こんなメソッドが定義されるようにしたい
define_method
Googleさんに聞いたところ「define_method」っていうメソッドを使うと実現できるらしい。
define_method("push_0") { @disp = @disp * 10 + 0 }
って書くと
def push_0 @disp = @disp * 10 + 0 end
↑のようなメソッドが定義されるみたいだ。
やってみよう
上の例を応用して、「push_0」〜「push_9」までのメソッドを一気に定義してしまおう。
class Calc def_push_nums 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 def def_push_nums(*nums) nums.each{ |num| define_method("push_#{num}") { @disp = @disp * 10 + num } } end end
これでいいはずだ。いけー!
calc.rb:3: undefined method `def_push_nums' for Calc:Class (NoMethodError)
( ゚д゚) ・・・
ダメだった
「def_push_nums」が定義されていませんって言われてしまった。クラスを定義する時点で「def_push_nums」が定義されていないからダメということなんだろうなあ。
じゃあなんで「attr_accessor」はダメじゃないんだろう。不公平だー!
調べてみたところ、「attr_accessor」はModuleクラスのメソッドでした。そしてClassクラスはModuleクラスを継承しているらしい。しかる故にClassクラスのインスタンスである全てのクラスは、最初から「attr_accessor」を使うことができるのでありました。
わからん!
あまりにも分からなすぎて泣きたくなってきた。
やり直し
深入りしすぎたようだ。簡単に実装できる方法に切り替えよう。
class Calc def initialize @disp = 0; end def push(num) @disp = @disp * 10 + num end def display @disp end end
テストケースも書き直し
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..' , 'lib') require 'test/unit' require 'calc' # 電卓クラスのテストケース class TestCalc < Test::Unit::TestCase # 初期化メソッド。各テストメソッドの前に実行される。 def setup @calc = Calc.new end # 数字ボタンのテスト [0] [1] [0] の順に押す def test_push_0 assert_equal(0, @calc.push(0)) assert_equal(0, @calc.display) assert_equal(1, @calc.push(1)) assert_equal(1, @calc.display) assert_equal(10, @calc.push(0)) assert_equal(10, @calc.display) end end
よっしゃ。テスト通ったー。今日はココまで
思ったこと
電卓クラスはいつになったら完成するんだ(トホホ・・・)