llonsen object ruby
DESCRIPTION
2008年11月のLL温泉でRubyの話をした時の資料TRANSCRIPT
![Page 1: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/1.jpg)
Rubyの基本LL温泉 2008/11/14~16
Takeshi AKIMA
![Page 2: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/2.jpg)
agenda•はじめに
•メソッドの基本
•基本的なクラスを押さえる
•ブロックの基本
•モジュールの基本
![Page 3: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/3.jpg)
はじめに対象者をちょっとRubyを触ったことがある人に限らず、基本的な部分をひたすら試していきます
楽しんでいきましょー!
Happy Hacking!
![Page 4: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/4.jpg)
irb•対話型のRubyの実行環境
•コンソール(コマンドプロンプト)で
> irb
で実行
•今日は基本これでやるよ
![Page 5: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/5.jpg)
Rubyのリファレンス•困ったらここを見よう
http://www.ruby-lang.org/ja/man/
•最新版はあるんだけど、これで勉強した僕としては、ここが一番!
•でもちょっと取っ付きにくいので、他のを見てもOK
![Page 6: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/6.jpg)
try!try!
メソッドの基本
•処理の基本はとにかくメソッドっす
•「クラスとは」とか言わずに、ひとまずやってみようぜ~
•例えば、fooって出力するfooメソッドを持っているオブジェクト、どう作る?
![Page 7: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/7.jpg)
こんな感じが普通かな?class Foo def foo puts "foo" endendobj = Foo.newobj.foo
![Page 8: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/8.jpg)
でもね、こんな風にも書けるよ
obj = Object.newdef obj.foo puts "foo"endobj.foo
![Page 9: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/9.jpg)
ちょっと変かもだけどさ・・・
•ふつーはクラスを作ることを考えるかもしれないけど、それって絶対?
•クラスを考えなくてもいい時があるんじゃない?
•クラスじゃなくてオブジェクトを中心に考えていこう!
![Page 10: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/10.jpg)
メソッドの呼び出し?いやいや、メッセージ送信!
•「メソッドの呼び出しをメッセージ送信と呼ぶ」なんてオブジェクト指向の本に書いてあるけど、それはそういう言い方をするだけだよね?なんて思っているアナタ!Rubyでは違うんだよ~
![Page 11: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/11.jpg)
必ず戻り値があるよobj = Object.newdef obj.fooendobj.foo
def obj.bar "BAR"endobj.bar
obj = Object.newdef obj.baz(a) if a.to_i > 0 return "a natural number" else "number?" endendobj.baz(2)obj.baz(-100)
![Page 12: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/12.jpg)
method_missingobj = Object.newdef obj.method_missing(method, *args) "message received! #{method}"endobj.fooobj.bar("XXXX")obj.baz(1, 2, 3, :x => 500, :y => 200)
![Page 13: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/13.jpg)
send
obj = Object.newdef obj.foo "FOO"endobj.fooobj.send('foo')
本当にメッセージを送ってる感じがするで
しょ?
![Page 14: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/14.jpg)
メッセージ受信可?obj = Object.newdef obj.foo puts "foo"endobj.respond_to?(:foo)obj.respond_to?(:bar)
![Page 15: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/15.jpg)
重要!
重要!
Rubyのメッセージング
•オブジェクトが本当にメッセージを送信してるのが体感できた?
•メソッドが定義されてなくても、
メッセージを送信することはできる!
==> 普通エラーになるけどね
![Page 16: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/16.jpg)
デフォルト引数を受け取ってみよう
obj = Object.newdef obj.foo(a, b = 1) "a => #{a.inspect}, b => #{b.inspect}"endobj.foo("A")obj.foo("B", 5)
![Page 17: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/17.jpg)
可変引数で何個でもobj = Object.newdef obj.foo(name, *args) "#{name} #{args.inspect}"endobj.foo("A")obj.foo("B", 1, 2)obj.foo("C", 1, 2, 3, 4, 5, 6, 7, 8, 9)
![Page 18: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/18.jpg)
名前付き引数?
obj = Object.newdef obj.foo(options) options.inspectendobj.foo(1)obj.foo(:name => "A", :no => 10)
![Page 19: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/19.jpg)
名前付き引数obj = Object.newdef obj.foo(a, b, options)endobj.foo(1, 2, :name => "A", :no => 10)obj.foo(1, 2, {:name => "A", :no => 10})obj.foo(1, {:name => "A", :no => 10}, 2)obj.foo(1, :name => "A", :no => 10, 2)上の2つのfooの呼び出しは全く同じ意味です。{}はHashという連想配列のオブジェクトね。引数の一番最後には{}を省略してHashを記述することができます
![Page 20: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/20.jpg)
変数、定数ローカル変数 一般的な変数。小文字で宣言されているもの。 慣習とし
ては、underscore_style
インスタンス変数 インスタンス毎に保持される変数。@が先頭に付きます。 慣習としては、@underscore_style
クラス変数 クラス毎に保持される変数。@@が先頭に付きます。 慣習としては、@@underscore_style
グローバル変数 $で始まるやつ。既にある奴を使うだけにしておこう!
定数 大文字で始まるもの。通常全部大文字のUNDERSCORE_STYLE
クラス名 大文字で始まるもの。通常CamelCaseStyle
![Page 21: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/21.jpg)
try!try!カウントさせよう
obj = Object.newdef obj.count_up # この中身を書くだけでできるはずendobj.count_up #=> 1obj.count_up #=> 2obj.count_up #=> 3
![Page 22: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/22.jpg)
関数ちっくに書く•Rubyではオブジェクトを省略してメソッドを書けるよ。まるで関数だね。
•実はKernelってやつのメソッドになります
• Kernel.methods.sort で調べてみてね
• Kernelについてはまた後で
def foo "FOO"end
![Page 23: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/23.jpg)
リファレンスと本だけが調べる術じゃないっす
•Rubyのオブジェクトは結構自分自身のことを語ってくれます。
![Page 24: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/24.jpg)
Object#methods
"ABC".methods:ABC.methods[1,2,3].methods{"A" => 1, "B" => 2}.methods1.methodstrue.metodsnil.methods
![Page 25: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/25.jpg)
Object#class"ABC".class:ABC.class[1,2,3].class{:a => 1, :b => 2}.classa = "ABC"a.is_a?(String)a.is_a?(Symbol)a.is_a?(Array)
![Page 26: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/26.jpg)
基本的なクラス
•押さえておきたいクラスはそんなに多くないっす
• Array, Hash, Symbol, Stringを押さえておけば、ひとまずはOK
![Page 27: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/27.jpg)
Strings = "ABC"s << "D"s += "EFG""a,b,c,d".split(',')"now: #{Time.now}""a,b,c,d".gsub(/b/, "B")"123".to_i"ABC"[1]"DEF".downcase"ghijk".include?("gh")
![Page 28: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/28.jpg)
Symbol
"a".to_sym:a.to_s"a".object_id"a".object_id:a.object_id:a.object_id
![Page 29: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/29.jpg)
Stringの問題try!try!
try!try!
try!try!
•文字列の中から数字のみを抜き出すpickup_numberメソッド
• SymbolかStringのオブジェクトを渡すと、末尾に _onsen が付いたSymbolを返す onsenizeメソッド
• s = "ABC" に対して以下の違いは何?s << "D"s += "D"
![Page 30: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/30.jpg)
Arraya = [1, 2, 3]a[1]a << 4a += [5, 6]a.lasta.popa[1..-2] = [20, 30, 40]a.join(",")a.each{|value| puts value}
[4, 6, 4, 9].sort[4, 6, 4, 9].reverse[4, 6, 4, 9].uniq
![Page 31: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/31.jpg)
try!try!
try!try!
try!try!
• get_at([1,2,3], :first) => 1get_at([1,2,3], :last) => 3となるようなget_atメソッド
•カンマ区切りの文字列をバラして、ソートするsplit_sortメソッド
•数値のみで構成される配列の要素の合計を求めるsum_arrayメソッド
Arrayの練習
![Page 32: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/32.jpg)
Hashh = {"A" => 65, "B" => 66}h["A"]h["C"]h["D"] = 67h.keysh.valuesh.each do |key, value| puts "#{key} => #{value}"end
![Page 33: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/33.jpg)
try!try!
try!try!
try!try!• Hashと文字列を渡すと、キーの一部が該当する値を配列で返す、select_valuesメソッド
•複数のHashの足し算をするmerge_hashメソッド(キーが重複したら上書きね)。def merge_hash(*hashes) って感じで
•どんなHashでもJSONのオブジェクトになる文字列 "{'キー': '値'}"にしちゃう、to_jsonメソッド
Hashの練習
![Page 34: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/34.jpg)
try!try!可変引数で、最後は名前付きの引数•これまでのテクを組み合わせればきっとできる!
• obj.foo(1, 2, 3) => [1, 2, 3] {:name => "A", :no => 1}
• obj.foo(1, 2, :name => "B") => [1, 2] {:name => "B", :no => 1}
• obj.foo(:name => "B") => [] {:name => "B", :no => 1}
• というfooをよろしく
![Page 35: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/35.jpg)
ブロックの基本
•メソッドよりも細かく処理の断片を記述するもの
•クロージャとか色んな呼び方があるけど、「ブロック」って呼んでね。
![Page 36: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/36.jpg)
重要!
重要!
ブロック[1, 2, 3, 4].each{|value| puts value}[1, 2, 3, 4].each do |value| puts valueend
「[1, 2, 3, 4]っていう配列のeachメソッドにブロックが渡されている」って読んでください。
![Page 37: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/37.jpg)
どんなメソッドでもブロックは受け取れる
def foo "FOO"endfoo{ puts "BAR" }
ただし、受け取るだけで勝手に呼び出すことはできないっす
![Page 38: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/38.jpg)
渡されたブロックを呼び出す
def foo yieldendfoo{ puts "BAR" }
def bar yield yield yieldendbar{ puts "BAR" }
![Page 39: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/39.jpg)
渡されたブロックに引数を渡して呼び出すdef foo yield("FOO")endfoo{ "BAR" }
foo{|v| v }
![Page 40: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/40.jpg)
ブロックの戻り値を使う
def foo yield * 100endfoo{ 1 }foo{ "BAR" }
![Page 41: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/41.jpg)
ブロックを他のメソッドに渡す
def foo yield("FOO")enddef bar(&block) foo(&block)endbar{|v| v * 3 }bar{|v| "C" + v }
![Page 42: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/42.jpg)
ブロックを他のメソッドに渡す
def foo yield("FOO")enddef bar foo{|v| yield(v) }endbar{|v| v * 3 }bar{|v| "C" + v }
![Page 43: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/43.jpg)
try!try!処理の順番のログがほしい!
def foo log("in foo"){ yield("FOO") }enddef bar log("in bar") do foo do |v| log("in block for foo"){ yield(v) } end endendbar do |v| log("in block for bar"){ v * 3 } end
in bar beforein foo beforein block for foo beforein block for bar beforein block for bar afterin block for foo afterin foo afterin bar after=> "FOOFOOFOO"
左のコードを実行したら、下のように出力されるlogメソッド。{}のブロックは、do...endに置き換えた方が分かるかも。
![Page 44: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/44.jpg)
モジュールの基本
•Rubyのモジュールは、メソッドは持ってるから、クラスっぽいけどインスタンスは作れないやつです
•モジュールを使うと、オブジェクトにメソッドを追加することができます
![Page 45: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/45.jpg)
オブジェクトにメソッドを追加する方法
•def obj.foo
• fooを持ったモジュールをobjにextend
• objのクラスで def foo
• fooを持ったモジュールをクラスにinclude
![Page 46: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/46.jpg)
オブジェクトに追加obj = Obj.newdef obj.fooendobj.bar
Object
obj
foo
![Page 47: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/47.jpg)
extendで追加obj = Obj.newobj.foomodule Foo def foo endendobj.extend(Foo)obj.foo
Object
obj foo
Foo
![Page 48: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/48.jpg)
普通にクラスで書く
class Foo def foo endendobj = Foo.newobj.foo
Object
foo
Foo
obj
![Page 49: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/49.jpg)
includeで追加class Barendobj = Bar.newobj.foomodule Foo def foo endendclass Bar include Fooendobj.foo
Object
Bar
obj
foo
Foo
![Page 50: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/50.jpg)
モジュールはモジュールをinclude可能
module Foo def foo; endendmodule Hoge include Fooendclass Bar include Hogeendobj = Bar.newobj.foo
Object
Bar
obj
foo
Foo
Hoge
![Page 51: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/51.jpg)
モジュールを何個でもinclude可能
module Foo def foo; endendmodule Baz; endmodule Hoge include Foo include Bazendmodule Fuga include Bazendclass Bar include Hoge include Fugaendobj = Bar.newobj.foo
Object
Bar
obj
foo
Foo
Hoge
Fuga
Baz
![Page 52: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/52.jpg)
重要!
重要!Enumerable重要!
•ArrayやHashなどRubyの便利なクラスがincludeしているモジュールです。
•ここには非常に便利なメソッドが沢山用意されています。
•map, select, any?, all?, inject・・・
![Page 53: Llonsen object ruby](https://reader035.vdocuments.mx/reader035/viewer/2022081403/556a3cd2d8b42a4a1e8b4746/html5/thumbnails/53.jpg)
もう一回練習
try!try!
try!try!•文字列の配列から各要素をn回繰り返し、それらをカンマで区切った文字列を返すrepeat_joinメソッド
•数値のみで構成される配列の要素から奇数を抽出して合計を出すodd_sumメソッド