リテラルの正体を暴く
演算子はメソッドの呼び出しですよ、というところからはじまって、オブジェクトやクラスの話になってしまいました。
もう一度演算子のところに戻ってみましょう。
11 + 5
たとえばこんな何の変哲も無い足し算すら、メソッドの呼び出しである、という主張でした。
今の私は、メソッドがあるからには、そこにはその『メソッドを持っているオブジェクトがある』はずだ、ということを知っています。
そうは云っても、現在『 + 』のほかの登場人物といえば『 11 』と『 5 』だけですね……
普通に考えてみたら、このどちらかが、『 + 』のメソッドを持っているはずです。
しかし、今回は同じ数値リテラルですから、どちらで考えても同じことです。結局、数値リテラルも実はオブジェクトだよ、ということになるのではないでしょうか。
オブジェクトということは、その基になるクラスが必ずあります。
それでは『 11 』や『 5 』は何というクラスのインスタンスなのでしょうか。
その正体は、『Fixnum』クラスです。
⇒Fixnum
ほんとかよ、って云われると困るので、ちょっと話が飛びますがオブジェクトのクラスを知る方法を紹介します。
例えば『 11 』のクラスが知りたければこのようにします。
puts 11.class
↓実行結果
Fixnum
このように、
<オブジェクト>.class
という形式で、そのオブジェクトが属するクラスを取得することができます(言い方を変えると、classというのはクラス名を返却するメソッドです)。
これを実行すれば、『 11 』はFixnumクラスのインスタンスである、ということが確認できると思います。
同じように、"Hello"のような文字列リテラルや、3.14のような浮動小数点数でもクラス名を確認できます。
puts "Hello".class puts 3.14.class
↓実行結果
String Float
文字列リテラルはStringクラスのインスタンスで、浮動小数点数はFloatクラスのインスタンスのようです。
これらはそれぞれ、String型・Float型というような言い方をされることもあります。
ともあれ、数値リテラルはオブジェクトで、四則演算しているときも実際は定義されているメソッドを呼び出しているんだよ、というのがなんとなくわかってきました。
ついでなので、本当にそんなメソッドが定義されているのかも見てみたいと思います。
オブジェクトの持つメソッドを知るには、たとえば次のようにします。
puts 11.methods
methodsというのは、オブジェクトの持つメソッドの一覧を返却するメソッドで、
<オブジェクト>.methods
という形式で呼び出すことができます。
実行するとずらずらっと色々表示されて、その中に『 + 』とか『 / 』とか『 class 』とか『 methods 』自身も確認できると思います。
演算子も確かにメソッドでした……ふーむ。
ゆとり教育の正体は?
そういえば前回、
puts 11 / 3
を実行したら
3
が出てくる、ということで文句を云ってみました。
これについては通りすがりさんが
11 / 3 は、整数同士の割り算だから、答えも整数。
小数点の答えをほしい場合はどちらかを小数にする必要がある。
puts( 11.0 / 3 )
ここからへんは、数値クラスについて、マニュアルにいろいろと書いてある。
とコメントで教えてくださいました。ありがとうございます。
そんなわけで早速マニュアルを見てみましょう。
⇒数値関連クラスの定義メソッド
ここまでで、数値関連のクラスではFixnumとFloatを確認しています。
Rubyにおける数値型は、実際にはNumericというクラスを頂点とした継承関係を築いているようです。
前回の問題は結局のところ、『Fixnumクラス(というかIntegerクラス)の / メソッドは、引数がIntegerであるとき、Integerの結果を返却する』ように定義されている、ということなのだと思います。
通りすがりさんがおっしゃっているように、どちらかのオペランドの型をFloatにすれば解決です。
レシーバ
ここまでなんの断りもなく書いてきましたが、一応確認しておきます。
オブジェクトのデータやメソッドを表す場合は、
オブジェクト.データ オブジェクト.メソッド
という具合に、.(ドット:ピリオド)で繋いで関係を表現します。
このとき、.の左側にあるものを“レシーバ”と呼びます。
このあたりは、リファレンスマニュアルを確認すると良さそうです。
⇒メソッド呼び出し
さらりと書いちゃってますが、意外と重要です。レシーバ。すいません。
さてさてこんな風に呼び出すメソッドですが、以前数値を10進数以外の形式で表示させた際にも、このようにしてちゃっかりメソッドを利用しました。
puts '■10進整数\n' puts 123.to_s(16) # 16進表記 puts -123.to_s(8) # 8進表記 puts 0d123.to_s(2) # 2進表記 puts '■16進整数' puts 0xffff.to_s(16) puts '■2進整数' puts 0b1011.to_s(2) puts '■8進整数' puts 0377.to_s(8) puts 0o377.to_s(8)
ここで使っているto_sメソッドは、引数で指定した基数による文字列表現に変換するメソッドです。
このような『to_なんとか』メソッドは、Rubyでは(なんとか型に)変換を行うメソッドに付けられる名前になっています。
to_sのsはString(文字列)のsなので、文字列表現に変換、という機能になるわけですね。
同じような感じで、to_f(to Float)なんていうメソッドもあって、これを使った場合だとFloatに変換できるわけです。
ということは、
puts (11 / 3).to_f
とすればいい感じの結果が!
↓
3.0
……でません。
既に計算してしまった結果に対して変換をかけているので、あたりまえですね。
なので、こんな風にします。
puts (11.to_f / 3) puts (11 / 3.to_f) puts (11.to_f / 3.to_f)
これで完璧です。要するに演算前(メソッド呼び出し前)に適切な型にしておく必要があるよ、ということです。
でもまぁ素直に浮動小数点数リテラル使えばいいと思います。