llonsen object ruby

53
Rubyの基本 LL温泉 2008/11/14~16 Takeshi AKIMA

Upload: takeshi-akima

Post on 31-May-2015

535 views

Category:

Technology


0 download

DESCRIPTION

2008年11月のLL温泉でRubyの話をした時の資料

TRANSCRIPT

Page 1: Llonsen object ruby

Rubyの基本LL温泉 2008/11/14~16

Takeshi AKIMA

Page 2: Llonsen object ruby

agenda•はじめに

•メソッドの基本

•基本的なクラスを押さえる

•ブロックの基本

•モジュールの基本

Page 3: Llonsen object ruby

はじめに対象者をちょっとRubyを触ったことがある人に限らず、基本的な部分をひたすら試していきます

楽しんでいきましょー!

Happy Hacking!

Page 4: Llonsen object ruby

irb•対話型のRubyの実行環境

•コンソール(コマンドプロンプト)で

> irb

で実行

•今日は基本これでやるよ

Page 5: Llonsen object ruby

Rubyのリファレンス•困ったらここを見よう

http://www.ruby-lang.org/ja/man/

•最新版はあるんだけど、これで勉強した僕としては、ここが一番!

•でもちょっと取っ付きにくいので、他のを見てもOK

Page 6: Llonsen object ruby

try!try!

メソッドの基本

•処理の基本はとにかくメソッドっす

•「クラスとは」とか言わずに、ひとまずやってみようぜ~

•例えば、fooって出力するfooメソッドを持っているオブジェクト、どう作る?

Page 7: Llonsen object ruby

こんな感じが普通かな?class Foo def foo puts "foo" endendobj = Foo.newobj.foo

Page 8: Llonsen object ruby

でもね、こんな風にも書けるよ

obj = Object.newdef obj.foo puts "foo"endobj.foo

Page 9: Llonsen object ruby

ちょっと変かもだけどさ・・・

•ふつーはクラスを作ることを考えるかもしれないけど、それって絶対?

•クラスを考えなくてもいい時があるんじゃない?

•クラスじゃなくてオブジェクトを中心に考えていこう!

Page 10: Llonsen object ruby

メソッドの呼び出し?いやいや、メッセージ送信!

•「メソッドの呼び出しをメッセージ送信と呼ぶ」なんてオブジェクト指向の本に書いてあるけど、それはそういう言い方をするだけだよね?なんて思っているアナタ!Rubyでは違うんだよ~

Page 11: Llonsen object ruby

必ず戻り値があるよ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

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

send

obj = Object.newdef obj.foo "FOO"endobj.fooobj.send('foo')

本当にメッセージを送ってる感じがするで

しょ?

Page 14: Llonsen object ruby

メッセージ受信可?obj = Object.newdef obj.foo puts "foo"endobj.respond_to?(:foo)obj.respond_to?(:bar)

Page 15: Llonsen object ruby

重要!

重要!

Rubyのメッセージング

•オブジェクトが本当にメッセージを送信してるのが体感できた?

•メソッドが定義されてなくても、

メッセージを送信することはできる!

==> 普通エラーになるけどね

Page 16: Llonsen object ruby

デフォルト引数を受け取ってみよう

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

可変引数で何個でも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

名前付き引数?

obj = Object.newdef obj.foo(options) options.inspectendobj.foo(1)obj.foo(:name => "A", :no => 10)

Page 19: Llonsen object ruby

名前付き引数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

変数、定数ローカル変数 一般的な変数。小文字で宣言されているもの。 慣習とし

ては、underscore_style

インスタンス変数 インスタンス毎に保持される変数。@が先頭に付きます。 慣習としては、@underscore_style

クラス変数 クラス毎に保持される変数。@@が先頭に付きます。 慣習としては、@@underscore_style

グローバル変数 $で始まるやつ。既にある奴を使うだけにしておこう!

定数 大文字で始まるもの。通常全部大文字のUNDERSCORE_STYLE

クラス名 大文字で始まるもの。通常CamelCaseStyle

Page 21: Llonsen object ruby

try!try!カウントさせよう

obj = Object.newdef obj.count_up # この中身を書くだけでできるはずendobj.count_up #=> 1obj.count_up #=> 2obj.count_up #=> 3

Page 22: Llonsen object ruby

関数ちっくに書く•Rubyではオブジェクトを省略してメソッドを書けるよ。まるで関数だね。

•実はKernelってやつのメソッドになります

• Kernel.methods.sort で調べてみてね

• Kernelについてはまた後で

def foo "FOO"end

Page 23: Llonsen object ruby

リファレンスと本だけが調べる術じゃないっす

•Rubyのオブジェクトは結構自分自身のことを語ってくれます。

Page 24: Llonsen object ruby

Object#methods

"ABC".methods:ABC.methods[1,2,3].methods{"A" => 1, "B" => 2}.methods1.methodstrue.metodsnil.methods

Page 25: Llonsen object ruby

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

基本的なクラス

•押さえておきたいクラスはそんなに多くないっす

• Array, Hash, Symbol, Stringを押さえておけば、ひとまずはOK

Page 27: Llonsen object ruby

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

Symbol

"a".to_sym:a.to_s"a".object_id"a".object_id:a.object_id:a.object_id

Page 29: Llonsen object ruby

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

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

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

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

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

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

ブロックの基本

•メソッドよりも細かく処理の断片を記述するもの

•クロージャとか色んな呼び方があるけど、「ブロック」って呼んでね。

Page 36: Llonsen object ruby

重要!

重要!

ブロック[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

どんなメソッドでもブロックは受け取れる

def foo "FOO"endfoo{ puts "BAR" }

ただし、受け取るだけで勝手に呼び出すことはできないっす

Page 38: Llonsen object ruby

渡されたブロックを呼び出す

def foo yieldendfoo{ puts "BAR" }

def bar yield yield yieldendbar{ puts "BAR" }

Page 39: Llonsen object ruby

渡されたブロックに引数を渡して呼び出すdef foo yield("FOO")endfoo{ "BAR" }

foo{|v| v }

Page 40: Llonsen object ruby

ブロックの戻り値を使う

def foo yield * 100endfoo{ 1 }foo{ "BAR" }

Page 41: Llonsen object ruby

ブロックを他のメソッドに渡す

def foo yield("FOO")enddef bar(&block) foo(&block)endbar{|v| v * 3 }bar{|v| "C" + v }

Page 42: Llonsen object ruby

ブロックを他のメソッドに渡す

def foo yield("FOO")enddef bar foo{|v| yield(v) }endbar{|v| v * 3 }bar{|v| "C" + v }

Page 43: Llonsen object ruby

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

モジュールの基本

•Rubyのモジュールは、メソッドは持ってるから、クラスっぽいけどインスタンスは作れないやつです

•モジュールを使うと、オブジェクトにメソッドを追加することができます

Page 45: Llonsen object ruby

オブジェクトにメソッドを追加する方法

•def obj.foo

• fooを持ったモジュールをobjにextend

• objのクラスで def foo

• fooを持ったモジュールをクラスにinclude

Page 46: Llonsen object ruby

オブジェクトに追加obj = Obj.newdef obj.fooendobj.bar

Object

obj

foo

Page 47: Llonsen object ruby

extendで追加obj = Obj.newobj.foomodule Foo def foo endendobj.extend(Foo)obj.foo

Object

obj foo

Foo

Page 48: Llonsen object ruby

普通にクラスで書く

class Foo def foo endendobj = Foo.newobj.foo

Object

foo

Foo

obj

Page 49: Llonsen object ruby

includeで追加class Barendobj = Bar.newobj.foomodule Foo def foo endendclass Bar include Fooendobj.foo

Object

Bar

obj

foo

Foo

Page 50: Llonsen object ruby

モジュールはモジュールを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

モジュールを何個でも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

重要!

重要!Enumerable重要!

•ArrayやHashなどRubyの便利なクラスがincludeしているモジュールです。

•ここには非常に便利なメソッドが沢山用意されています。

•map, select, any?, all?, inject・・・

Page 53: Llonsen object ruby

もう一回練習

try!try!

try!try!•文字列の配列から各要素をn回繰り返し、それらをカンマで区切った文字列を返すrepeat_joinメソッド

•数値のみで構成される配列の要素から奇数を抽出して合計を出すodd_sumメソッド