155
青青青青 青青青青 日日 日日 Ruby Ruby 日日 日日 13-B-3 青青青青 青青青青 Ruby Ruby 青青青青青青青青 青青青青青青青青 Ruby Ruby 青青青青青青青青青 青青青青青青青青青

青木峰郎 日本 Ruby の会

  • Upload
    eavan

  • View
    123

  • Download
    0

Embed Size (px)

DESCRIPTION

ふつうの Ruby プログラマに贈る Ruby プログラミング講座. 13-B-3. 青木峰郎 日本 Ruby の会. 自己紹介. 青木峰郎 (日本 Ruby の会). Ruby がらみで やってること. Ruby 関係のおしごと. 書籍 『Rubyist Magazine 出張版 』 MYCOM 書籍 『Ruby レシピブック第二版 』 SBC r 書籍 『Ruby ソースコード完全解説 』 Impress 書籍 『Ruby を 256 倍使う本 無道編 』 ASCII リファレンスマニュアル刷新計画 隊長 - PowerPoint PPT Presentation

Citation preview

Page 1: 青木峰郎 日本 Ruby の会

青木峰郎青木峰郎日本日本 RubyRuby の会の会13-B-3

ふつうのふつうの RubyRuby プログラマに贈プログラマに贈るる

RubyRuby プログラミング講座プログラミング講座

Page 2: 青木峰郎 日本 Ruby の会

自己紹介自己紹介

Page 3: 青木峰郎 日本 Ruby の会

青木峰郎青木峰郎(日本(日本 RubyRuby の会)の会)

Page 4: 青木峰郎 日本 Ruby の会

RubyRuby がらみでがらみでやってることやってること

Page 5: 青木峰郎 日本 Ruby の会

RubyRuby 関係のおしごと関係のおしごと

• 書籍書籍『『 Rubyist MagazineRubyist Magazine 出張版出張版 』 』 MYCOMMYCOM• 書籍書籍『『 RubyRuby レシピブック第二版レシピブック第二版 』 』 SBCSBC rr• 書籍書籍『『 RubyRuby ソースコード完全解説ソースコード完全解説 』 』 ImpressImpress• 書籍書籍『『 RubyRuby をを 256256 倍使う本 無道編倍使う本 無道編 』 』 ASCIIASCII• リファレンスマニュアル刷新計画 隊長リファレンスマニュアル刷新計画 隊長• 標準ライブラリいくつか標準ライブラリいくつか (net/http, fileutils, ...)(net/http, fileutils, ...)• それ以外のアプリ各種 それ以外のアプリ各種 (BitChannel,Racc, ..)(BitChannel,Racc, ..)

Page 6: 青木峰郎 日本 Ruby の会

まとめ:まとめ:

いろいろやってまいろいろやってます。す。

Page 7: 青木峰郎 日本 Ruby の会

今日の内容今日の内容

Page 8: 青木峰郎 日本 Ruby の会

agenda 1/2agenda 1/2第一部:第一部: RubyRuby プログラミングのツボプログラミングのツボ

1.1. protectedprotected

2.2. pp とと pppp

3.3. unlessunless とと untiluntil

4.4. クラスと名前空間クラスと名前空間5.5. ファイル名とクラス名ファイル名とクラス名6.6. 大クラス主義大クラス主義

Page 9: 青木峰郎 日本 Ruby の会

agenda 2/2agenda 2/2第二部:第二部: RubyRuby プログラミングの、押しすプログラミングの、押しす

ぎるとヤバいツボのうちのいくつかぎるとヤバいツボのうちのいくつか1.1. VisitorVisitor パターンめどいパターンめどい2.2. 1.81.8 とと 1.91.9 でメソッド違いすぎでメソッド違いすぎ wwwwww

Page 10: 青木峰郎 日本 Ruby の会

11 .. protectedprotected

Page 11: 青木峰郎 日本 Ruby の会

Q: protectedQ: protected使ってます使ってます

かか??

Page 12: 青木峰郎 日本 Ruby の会

protectedprotected は通常は通常必要ありませ必要ありませ

ん!ん!

Page 13: 青木峰郎 日本 Ruby の会

protectedprotected のの9595 %は間違%は間違

いい

Page 14: 青木峰郎 日本 Ruby の会

RailsRails もも使いかたを使いかたを間違ってた間違ってた

Page 15: 青木峰郎 日本 Ruby の会

RubyRuby のの protectedprotected ははJava/C++Java/C++ のの

protectedprotectedとは違うとは違う

Page 16: 青木峰郎 日本 Ruby の会

Java の可視性

可視性 意味

public 制限なくアクセスできる

protected

サブクラスと、パッケージ内のクラスからアクセスできる

private 同じクラスからのみアクセスできる

Page 17: 青木峰郎 日本 Ruby の会

Ruby の可視性

可視性 意味

public 制限なくアクセスできる

protected

そのクラスとサブクラスで、オブジェクトの外からアクセスできる

private 同じオブジェクト内からアクセスできる(クラスは関係ない)

Page 18: 青木峰郎 日本 Ruby の会

Java/C++Java/C++ はクラス単はクラス単位位

RubyRuby はオブジェクトはオブジェクト単位単位

Page 19: 青木峰郎 日本 Ruby の会

違いの出る場面違いの出る場面

Page 20: 青木峰郎 日本 Ruby の会

Ruby では private メソッドも継承する

class Adef m() puts “OK” endprivate :m

end

class B < Adef call_m m

end

end

フツーに呼べる

Page 21: 青木峰郎 日本 Ruby の会

protectedprotected の使いどこの使いどころろ

Page 22: 青木峰郎 日本 Ruby の会

Ruby で protected が活用できる場面

class SomeObject attr_reader :prop protected :prop

def ==(other) @prop == other.prop

endend

外から(レシーバをつけた形式で)呼

べる

Page 23: 青木峰郎 日本 Ruby の会

ぶっちゃけぶっちゃけprotectedprotected なんてなんて

使わない使わない

Page 24: 青木峰郎 日本 Ruby の会

結論:結論:RubyRuby ではではpublicpublic とと privateprivate だだけけ使ってれば使ってれば OKOK

Page 25: 青木峰郎 日本 Ruby の会

2. p2. p とと pppp

Page 26: 青木峰郎 日本 Ruby の会

Q: Q: pp メソッメソッドド

使ってます使ってますかか??

Page 27: 青木峰郎 日本 Ruby の会

p Object.newp Object.new

Page 28: 青木峰郎 日本 Ruby の会

printfprintf デバッグデバッグ(p(p デバッグ?デバッグ? ))

に便利に便利

Page 29: 青木峰郎 日本 Ruby の会

Q: Q: pppp メメソッドソッド

使ってます使ってますかか??

Page 30: 青木峰郎 日本 Ruby の会

require 'pp'require 'pp'pppp Object.newObject.new

Page 31: 青木峰郎 日本 Ruby の会

表示が見やすい 表示が見やすい pp

Page 32: 青木峰郎 日本 Ruby の会

C:\>ruby -e "p File.stat('.')"C:\>ruby -e "p File.stat('.')"#<File::Stat dev=0x2, ino=0, #<File::Stat dev=0x2, ino=0, mode=040755, nlink=1, uid=0, mode=040755, nlink=1, uid=0, gid=0, rdev=0x2, size=0, gid=0, rdev=0x2, size=0, blksize=nil, blocks=nil, blksize=nil, blocks=nil, atime=Wed Feb 13 06:55:59 +0900 atime=Wed Feb 13 06:55:59 +0900 2008, mtime=Sun Feb 13 21:03:44 2008, mtime=Sun Feb 13 21:03:44 +0900 2008, ctime=Thu Jun 29 +0900 2008, ctime=Thu Jun 29 16:52:04 +0900 2006>16:52:04 +0900 2006>

Page 33: 青木峰郎 日本 Ruby の会

C:\>ruby -rpp -e "pp File.stat('.')"C:\>ruby -rpp -e "pp File.stat('.')"#<File::Stat#<File::Stat dev=0x2, dev=0x2, ino=0, ino=0, mode=040755 (directory rwxr-xr-x), mode=040755 (directory rwxr-xr-x), nlink=1, nlink=1, uid=0, uid=0, gid=0, gid=0, rdev=0x2 (0, 0), rdev=0x2 (0, 0), size=0, size=0, blksize=nil, blksize=nil, blocks=nil, blocks=nil, atime=Wed Feb 13 06:55:59 +0900 2008 atime=Wed Feb 13 06:55:59 +0900 2008 (1202853359),(1202853359), mtime=Sun Feb 03 21:03:44 +0900 2008 mtime=Sun Feb 03 21:03:44 +0900 2008 (1202040224),(1202040224), ctime=Thu Jun 29 16:52:04 +0900 2006 ctime=Thu Jun 29 16:52:04 +0900 2006 (1151567524)>(1151567524)>

Page 34: 青木峰郎 日本 Ruby の会

pp のしくみのしくみ

Page 35: 青木峰郎 日本 Ruby の会

def p(obj)def p(obj) puts puts obj.inspectobj.inspectendend

Page 36: 青木峰郎 日本 Ruby の会

出力先は出力先はstdoutstdout

Page 37: 青木峰郎 日本 Ruby の会

誰もが誰もが stderrstderr にに出力されることを期待し出力されることを期待しそして裏切られるそして裏切られる

Page 38: 青木峰郎 日本 Ruby の会

inspectinspect をを自分で定義すれば自分で定義すれば表示を変更できる表示を変更できる

Page 39: 青木峰郎 日本 Ruby の会

to_sto_s とと inspectinspect の違の違いい

Page 40: 青木峰郎 日本 Ruby の会

メソッド 用途

to_s オブジェクトを文字列に変換するとき。

inspect オブジェクトをデバッグのために表示するとき。

Page 41: 青木峰郎 日本 Ruby の会

inspectinspect ははデバッグ用途にだけデバッグ用途にだけ

使おう!使おう!

Page 42: 青木峰郎 日本 Ruby の会

3. unless3. unless ととuntiluntil

Page 43: 青木峰郎 日本 Ruby の会

Q: Q: unlessunless使ってます使ってます

かか??

Page 44: 青木峰郎 日本 Ruby の会

Q: Q: untiluntil使ってます使ってます

かか??

Page 45: 青木峰郎 日本 Ruby の会

unless = if notunless = if notuntil = while notuntil = while not

Page 46: 青木峰郎 日本 Ruby の会

制御構造は制御構造はえり好みせず使おえり好みせず使お

うう

Page 47: 青木峰郎 日本 Ruby の会

ただしただし redoredo を除くを除く

Page 48: 青木峰郎 日本 Ruby の会

多様な意図を多様な意図を表現するには表現するには

多様な制御構造を多様な制御構造を使ったほうがいい使ったほうがいい

Page 49: 青木峰郎 日本 Ruby の会

「「 if/whileif/while でで書けるから書けるから

いらない」?いらない」?

Page 50: 青木峰郎 日本 Ruby の会

あらゆる制御構造はあらゆる制御構造はgotogoto で実現できますで実現できます

Page 51: 青木峰郎 日本 Ruby の会

プリミティブ症候群プリミティブ症候群にに

陥らないこと陥らないこと

Page 52: 青木峰郎 日本 Ruby の会

unlessunless の使いどこの使いどころろ

Page 53: 青木峰郎 日本 Ruby の会

前提条件の前提条件のチェックに使うとチェックに使うと

いいかんじいいかんじ

Page 54: 青木峰郎 日本 Ruby の会

def m(idx)def m(idx) raise IndexError, "out of raise IndexError, "out of range" \range" \ unless unless idx >= 0idx >= 0

unless を使うときは、「引数が満たすべき条件 (前提条

件)」を書けばよい

Page 55: 青木峰郎 日本 Ruby の会

untiluntil の使いどころの使いどころ

Page 56: 青木峰郎 日本 Ruby の会

終了条件をはっき終了条件をはっきりり

書きたいときに書きたいときに使う使う

Page 57: 青木峰郎 日本 Ruby の会

until until s.eos?s.eos? tok = s.scan(/\ tok = s.scan(/\w+/)w+/)

「スキャン中の文字列が尽きるまで( EOSになるまで)

~~する」

Page 58: 青木峰郎 日本 Ruby の会

4. 4. クラスとクラスと名前空間名前空間

Page 59: 青木峰郎 日本 Ruby の会

モジュールのモジュールのネスト、してますネスト、してます

か?か?

Page 60: 青木峰郎 日本 Ruby の会

module Cflatmodule Cflat class Node class Node .... .... end end class IfNode < Node class IfNode < Node .... .... end end class WhileNode < Node class WhileNode < Node .... .... end endendend

Page 61: 青木峰郎 日本 Ruby の会

モジュール・クラモジュール・クラスはスは

クラスの名前空間クラスの名前空間をを

兼ねている兼ねている

Page 62: 青木峰郎 日本 Ruby の会

module Cflatmodule Cflat class Node class Node .... .... end endendend

module MyCompilermodule MyCompiler class Node class Node .... .... end endendend

Page 63: 青木峰郎 日本 Ruby の会

別のモジュールに別のモジュールにネストしていればネストしていれば

クラス名がクラス名が同じでも大丈夫同じでも大丈夫

Page 64: 青木峰郎 日本 Ruby の会

JavaJava で言うパッケーで言うパッケージジ

C++C++ で言うで言うnamespacenamespace

Page 65: 青木峰郎 日本 Ruby の会

module Cflatmodule Cflat class Node class Node .... .... end endendend

p Cflat::Node.newp Cflat::Node.new

Page 66: 青木峰郎 日本 Ruby の会

ネスト構造の指針ネスト構造の指針

Page 67: 青木峰郎 日本 Ruby の会

第1レベル:第1レベル:アプリケーション名とアプリケーション名と

同名のモジュール同名のモジュール

例: 例: CflatCflat

Page 68: 青木峰郎 日本 Ruby の会

第2レベル:第2レベル:クラス名クラス名

例: 例: Compiler, Parser, Compiler, Parser, Node, ...Node, ...

Page 69: 青木峰郎 日本 Ruby の会

以上以上

Page 70: 青木峰郎 日本 Ruby の会

ネストはネストは深くしすぎないこ深くしすぎないこ

とと(せいぜい3段)(せいぜい3段)

Page 71: 青木峰郎 日本 Ruby の会

深くしすぎると深くしすぎると……

Page 72: 青木峰郎 日本 Ruby の会

module Cflatmodule Cflat module Frontend module Frontend module AST module AST class Node class Node .... .... end end end end endendendend

Page 73: 青木峰郎 日本 Ruby の会

単純に、単純に、見た目が見た目が

よろしくない!よろしくない!

Page 74: 青木峰郎 日本 Ruby の会

5. 5. ファイルファイル名とクラス名名とクラス名

Page 75: 青木峰郎 日本 Ruby の会

RubyRuby でのでのファイル名ファイル名

(ライブラリ名)(ライブラリ名)の決めかたの決めかた

Page 76: 青木峰郎 日本 Ruby の会

ファイル中でファイル中で最も代表的な最も代表的な

クラスの名前をクラスの名前を元に決める元に決める

Page 77: 青木峰郎 日本 Ruby の会

class Nodeclass Node .... ....class IfNode < Nodeclass IfNode < Node .... ....class WhileNode < class WhileNode < NodeNode .... ....

Page 78: 青木峰郎 日本 Ruby の会

代表的なクラス代表的なクラスはは

NodeNode クラスクラス

Page 79: 青木峰郎 日本 Ruby の会

ファイル名はファイル名はクラスクラス

名名 .downcase.downcase

Page 80: 青木峰郎 日本 Ruby の会

NodeNode クラスクラス

node.rbnode.rbdowncase

Page 81: 青木峰郎 日本 Ruby の会

クラスがクラスがネストしている場ネストしている場

合合

Page 82: 青木峰郎 日本 Ruby の会

module Cflatmodule Cflat class Node class Node .... .... class IfNode < class IfNode < NodeNode .... .... class WhileNode < class WhileNode < NodeNode .... ....

Page 83: 青木峰郎 日本 Ruby の会

クラス階層をクラス階層をディレクトリ階層ディレクトリ階層

にに反映させる反映させる

Page 84: 青木峰郎 日本 Ruby の会

Cflat::NodeCflat::Node クラスクラス cflat/node.rbcflat/node.rb

downcase

Page 85: 青木峰郎 日本 Ruby の会

そのほかの指針そのほかの指針

Page 86: 青木峰郎 日本 Ruby の会

1. 1. 関連するクラス関連するクラスはは

すべてすべて 11 つのつのファイルにまとめファイルにまとめ

るる

Page 87: 青木峰郎 日本 Ruby の会

JavaJava じゃじゃないんだからないんだから

Page 88: 青木峰郎 日本 Ruby の会

2. 2. ネストはネストはあまり深くしないあまり深くしない

(再)(再)

Page 89: 青木峰郎 日本 Ruby の会

JavaJava じゃじゃないのでないので

Page 90: 青木峰郎 日本 Ruby の会

6. 6. 大クラス主大クラス主義義

Page 91: 青木峰郎 日本 Ruby の会

大クラス主義大クラス主義……いろいろな仕事をいろいろな仕事を

11 つのクラスに行わせるつのクラスに行わせる設計ポリシーのこと設計ポリシーのこと

Page 92: 青木峰郎 日本 Ruby の会

例1例1

Page 93: 青木峰郎 日本 Ruby の会

RubyRuby のの ArrayArray はは配列とリストと配列とリストと

スタックとキューをスタックとキューを兼ねている兼ねている

Page 94: 青木峰郎 日本 Ruby の会

# # 配列として使う配列として使うarray = []array = []array[0] = 3array[0] = 3array[1] = 6array[1] = 6p array[0] # => 3p array[0] # => 3p array[1] # => 6p array[1] # => 6

Page 95: 青木峰郎 日本 Ruby の会

# # スタックとして使うスタックとして使うstack = []stack = []stack.push 1stack.push 1stack.push 2stack.push 2p stack.pop # => 2p stack.pop # => 2p stack.pop # => 1p stack.pop # => 1

Page 96: 青木峰郎 日本 Ruby の会

# # キューとして使うキューとして使うqueue = []queue = []queue.push 1queue.push 1queue.push 2queue.push 2p queue.shift # => 1p queue.shift # => 1p queue.shift # => 2p queue.shift # => 2

Page 97: 青木峰郎 日本 Ruby の会

例2例2

Page 98: 青木峰郎 日本 Ruby の会

RubyRuby のの StringString ははStringBuffer/StringBuffer/

StringBuilderStringBuilder をを兼ねている兼ねている

Page 99: 青木峰郎 日本 Ruby の会

# # 文字列をバッファ的に使う文字列をバッファ的に使うbuf = ''buf = ''buf << "line 1\n"buf << "line 1\n"buf << "another line\buf << "another line\n"n"buf << "extra line\n"buf << "extra line\n"puts bufputs buf

Page 100: 青木峰郎 日本 Ruby の会

それでそれでいいのか?いいのか?

Page 101: 青木峰郎 日本 Ruby の会

ぜんぜんぜんぜん OKOK

Page 102: 青木峰郎 日本 Ruby の会

だってだってうまくいってるうまくいってる

じゃんじゃん

Page 103: 青木峰郎 日本 Ruby の会

マイクロカーネルマイクロカーネルVSVS

モノリシックカーモノリシックカーネルネル

論争に類似?論争に類似?

Page 104: 青木峰郎 日本 Ruby の会

コンポーネントコンポーネント(クラス)が増え(クラス)が増え

るとるとコンポーネント間コンポーネント間

のの複雑性が増す複雑性が増す

Page 105: 青木峰郎 日本 Ruby の会

結局はバランス結局はバランス

Page 106: 青木峰郎 日本 Ruby の会

第一部 完第一部 完

Page 107: 青木峰郎 日本 Ruby の会

第二部第二部

Page 108: 青木峰郎 日本 Ruby の会

agenda 2/2agenda 2/2 (真)(真)第二部:第二部: RubyRuby プログラミングの、押しすプログラミングの、押しす

ぎるとヤバいツボのうちのいくつかぎるとヤバいツボのうちのいくつか1.1. sendsend を使ってクラス分岐を書くを使ってクラス分岐を書く2.2. リフレクションを使ってリフレクションを使って RubyRuby のバーのバー

ジョン間の差を埋めるジョン間の差を埋める

Page 109: 青木峰郎 日本 Ruby の会

1. 1. sendsend を使ってを使ってクラス分岐を書クラス分岐を書

くく

Page 110: 青木峰郎 日本 Ruby の会

問題:たくさんの問題:たくさんのクラスがあって、クラスがあって、

クラスごとにクラスごとに処理を変えたい処理を変えたい

Page 111: 青木峰郎 日本 Ruby の会

クラスごとにクラスごとに処理を変えると言え処理を変えると言え

ばばとりあえず多態とりあえず多態

(( polymorphismpolymorphism ))

Page 112: 青木峰郎 日本 Ruby の会

class class 鳥鳥 def def 鳴け鳴け () puts "() puts " ぽーぽー " end" endendendclass class 牛牛 def def 鳴け鳴け () puts "() puts " もーもー " end" endendendclass class 豚豚 def def 鳴け鳴け () puts "() puts " ぶーぶー " end" endendend

def def 鳴かせる鳴かせる (animal)(animal) animal. animal. 鳴け鳴けendend

鳴かせる鳴かせる (( 鳥鳥 .new).new)鳴かせる鳴かせる (( 牛牛 .new).new)

Page 113: 青木峰郎 日本 Ruby の会

11 つの処理がつの処理が複数クラスに複数クラスに

細切れにされてしま細切れにされてしまうう

Page 114: 青木峰郎 日本 Ruby の会

11 つの処理はつの処理は11 つのクラスにつのクラスにまとめたい!まとめたい!

Page 115: 青木峰郎 日本 Ruby の会

# # こんな感じにまとめたいこんな感じにまとめたい

class class 動物を鳴かせる動物を鳴かせる def def 鳴かせる鳴かせる (animal) (animal) ここのコードが問題ここのコードが問題 endend def def 鳥を鳴かす鳥を鳴かす () puts "() puts " ぽーぽー " end" end def def 牛を鳴かす牛を鳴かす () puts "() puts " もーもー " end" end def def 豚を鳴かす豚を鳴かす () puts "() puts " ぶーぶー " end" endendend

動物を鳴かせる動物を鳴かせる .new..new. 鳴かせる鳴かせる (( 鳥鳥 .new).new)動物を鳴かせる動物を鳴かせる .new..new. 鳴かせる鳴かせる (( 牛牛 .new).new)

Page 116: 青木峰郎 日本 Ruby の会

VisitorVisitor パターパターン?ン?

Page 117: 青木峰郎 日本 Ruby の会

VisitorVisitor パターンはパターンは実装がめんどくさい実装がめんどくさい

Page 118: 青木峰郎 日本 Ruby の会

そこでそこでsendsend

Page 119: 青木峰郎 日本 Ruby の会

Object#sendObject#send はは「メソッドを呼ぶ「メソッドを呼ぶ

メソッド」メソッド」

Page 120: 青木峰郎 日本 Ruby の会

obj.send(obj.send( メソッド名メソッド名 , , 本来の本来の引数引数 ))

Page 121: 青木峰郎 日本 Ruby の会

p "str".sizep "str".size

send化

p "str".send(:size)p "str".send(:size)

Page 122: 青木峰郎 日本 Ruby の会

sendsend を使ってを使ってクラス分岐が書けるクラス分岐が書ける

Page 123: 青木峰郎 日本 Ruby の会

class class 動物を鳴かせる動物を鳴かせる def def 鳴かせる鳴かせる (animal)(animal) send "#{animal.class} send "#{animal.class} を鳴かすを鳴かす "" end end def def 鳥を鳴かす鳥を鳴かす () puts "() puts " ぽーぽー " end" end def def 牛を鳴かす牛を鳴かす () puts "() puts " もーもー " end" end def def 豚を鳴かす豚を鳴かす () puts "() puts " ぶーぶー " end" endendend

動物を鳴かせる動物を鳴かせる .new..new. 鳴かせる鳴かせる (( 鳥鳥 .new).new)動物を鳴かせる動物を鳴かせる .new..new. 鳴かせる鳴かせる (( 牛牛 .new).new)

Page 124: 青木峰郎 日本 Ruby の会

2. 2. RubyRuby のバージョのバージョン間の差を埋めるン間の差を埋める

Page 125: 青木峰郎 日本 Ruby の会

1.9.01.9.0 リリースリリース

Page 126: 青木峰郎 日本 Ruby の会

しばらくはしばらくは1.81.8 とと 1.91.9 のの混在状態になる混在状態になる

Page 127: 青木峰郎 日本 Ruby の会

対応方針は対応方針は 22 つつ

Page 128: 青木峰郎 日本 Ruby の会

(1)(1) 1.91.9 は無視するは無視する

Page 129: 青木峰郎 日本 Ruby の会

現実的だが、現実的だが、現実的すぎて現実的すぎて

なんか腹立たしいなんか腹立たしい

Page 130: 青木峰郎 日本 Ruby の会

(2) (2) 両方のバージョ両方のバージョンン

で動くプログラムで動くプログラムを書くを書く

Page 131: 青木峰郎 日本 Ruby の会

RubyRuby の恐るべきの恐るべき非互換性の罠が非互換性の罠が待ち受ける待ち受ける

Page 132: 青木峰郎 日本 Ruby の会

例:例: sendsend の場合の場合

Page 133: 青木峰郎 日本 Ruby の会

sendsend ののもうもう 11 つの用途:つの用途:

privateprivate メソッドを呼メソッドを呼ぶぶ

Page 134: 青木峰郎 日本 Ruby の会

# Ruby 1.8# Ruby 1.8 の場合の場合

class Cclass C def m() puts "OK" end def m() puts "OK" end private :m private :mendend

C.new.m # C.new.m # これはダメこれはダメC.new.send(:m) # C.new.send(:m) # これなら通これなら通る!る!

Page 135: 青木峰郎 日本 Ruby の会

……ただし、ただし、Ruby 1.8Ruby 1.8 までなまでなら。ら。

Page 136: 青木峰郎 日本 Ruby の会

Ruby 1.9Ruby 1.9 (の一部)で(の一部)ではは

funcallfuncall を使わないとを使わないとprivateprivate メソッドがメソッドが

呼べない呼べない

Page 137: 青木峰郎 日本 Ruby の会

# # ありし日のありし日の Ruby 1.9Ruby 1.9 の場合の場合

class Cclass C def m() puts "OK" end def m() puts "OK" end private :m private :mendend

C.new.m # C.new.m # これはダメこれはダメC.new.send(:m) # C.new.send(:m) # これもダメこれもダメC.new.funcall(:m) # C.new.funcall(:m) # これなら通これなら通る!る!

Page 138: 青木峰郎 日本 Ruby の会

まとめまとめver. send funcall

Ruby

1.8

private メソッドを呼び出すことができる

存在しない

Ruby

1.9

private メソッドは呼び出せない

private メソッドを呼び出すことができる

Page 139: 青木峰郎 日本 Ruby の会

もうだめだもうだめだ……

Page 140: 青木峰郎 日本 Ruby の会

そんなあなたにそんなあなたにダイナミックダイナミック

プログラミングプログラミング

Page 141: 青木峰郎 日本 Ruby の会

「メソッドがないな「メソッドがないならら

定義すれば定義すればいいじゃない」いいじゃない」

Page 142: 青木峰郎 日本 Ruby の会

unless Object.method_defined?unless Object.method_defined?(:funcall)(:funcall) class Object class Object alias send funcall alias send funcall end endendend

Page 143: 青木峰郎 日本 Ruby の会

ポイント1ポイント1

Page 144: 青木峰郎 日本 Ruby の会

ifif 文や文や unlessunless 文の文のなかになかに classclass 文が文が

書ける書ける

Page 145: 青木峰郎 日本 Ruby の会

whilewhile 文の中にも文の中にもclassclass 文を書けるけど文を書けるけど

あんまり意味ないあんまり意味ない

Page 146: 青木峰郎 日本 Ruby の会

ポイント2ポイント2

Page 147: 青木峰郎 日本 Ruby の会

プログラムの実行時に、プログラムの実行時に、(既存の)クラスに(既存の)クラスに

メソッドを追加できるメソッドを追加できる

Page 148: 青木峰郎 日本 Ruby の会

オープンクラスオープンクラス(いつでも定義の(いつでも定義の

追加が可能なクラス)追加が可能なクラス)

Page 149: 青木峰郎 日本 Ruby の会

第二部 完第二部 完

Page 150: 青木峰郎 日本 Ruby の会

つづきはウェブでつづきはウェブで

Page 151: 青木峰郎 日本 Ruby の会

今日のまとめ今日のまとめ

Page 152: 青木峰郎 日本 Ruby の会

agenda 1/2agenda 1/2第一部:第一部: RubyRuby プログラミングのツボプログラミングのツボ

1.1. protectedprotected

2.2. pp とと pppp

3.3. unlessunless とと untiluntil

4.4. クラスと名前空間クラスと名前空間5.5. ファイル名とクラス名ファイル名とクラス名6.6. 大クラス主義大クラス主義

Page 153: 青木峰郎 日本 Ruby の会

agenda 2/2agenda 2/2 (真)(真)第二部:第二部: RubyRuby プログラミングの、押しすプログラミングの、押しす

ぎるとヤバいツボのうちのいくつかぎるとヤバいツボのうちのいくつか1.1. sendsend を使ってクラス分岐を書くを使ってクラス分岐を書く2.2. リフレクションを使ってリフレクションを使って RubyRuby のバーのバー

ジョン間の差を埋めるジョン間の差を埋める

Page 154: 青木峰郎 日本 Ruby の会

ご静聴ご静聴ありがとうありがとう

ございましたございました

Page 155: 青木峰郎 日本 Ruby の会

Q?Q?