Ruby初心者です。
あるコードの中にメソッド定義をしていないのに
普段みない方法でputsでclass名.new.nameみたいな感じで出力していました。
これは一体どういうことなのでしょうか?
どなたか何かご存知であれば教えてください。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
ベストアンサー
ご質問の内容だけですと可能性はいくつも考えられます。
- クラスの継承や mix-in をしている
- オープンクラスとして他のファイルで定義してる
- define_method や eval などで定義してる
- method_missing をオーバーライドしている
おそらく method_missing が一番気付きにくいので、そちらだとして説明します。
通常、未定義のメソッドを呼び出すとメソッドが未定義というエラー(NoMethodError)が発生します。
実際にはメソッドが見つからない場合 method_missing
というメソッドを呼び出して、その中でエラーを投げています。
そのため、method_missing
をオーバーライドして、メソッド名に合わせた処理を行えば、
あたかも定義した覚えのないメソッドが使えるようになります。
class Foo def method_missing(method_symbol, *args) if (method_symbol == :name) # メソッド名(シンボル名)が 「 name 」 の場合 self.class.to_s else # その他は親クラス(Object)の method_missing を呼び出す # → NoMethodError を発生させる super(method_symbol, *args) end end end p Foo.new.name # "Foo"
こういった機能は メタプログラミング といって、便利だけど危険なので、慣れないうちはあまり使うことのはお勧めしません。
ただ、 Rails などではこの機能が多用されていて、定義したはずのないメソッドをいろいろと使うことになります。こういったことができるというのは知っておいた方がいいと思います。
投稿2014/09/01 05:01
総合スコア863
0
それは method_missing を使っている例だったのではないかと想像されます。
以下は method_missing について説明します。
Rubyのmethod_missingの基本的な使い方 より引用。
...
class Clazz
def method_missing(name, *args)
puts "Method #{name} was called with #{args.map{|a| a.inspect}.join(',')}"
end
end
clazz = Clazz.new
clazz.hoge('foo', 'bar', 'buz') # => Method hoge was called with "foo","bar","buz"
...
上の例では、hoge() というメソッドを定義していないけど、hode(...) の呼び出しはエラーになりません。
hoge() の呼び出しは method_missing に制御が渡り、 メソッド名 "hoge" と 呼び出し時のパラメータが渡ります。
そして、上の例では、その メソッド名と呼び出し時のパラメータから文字列生成して返しています。
実際の利用に際しては method_missing の中での処理をいろいろ工夫をします。
例:
xml を生成する場合、どんなタグ名を出力するかは利用状況に左右されます。
タグ種類毎に メソッドを用意するというのは不可能です。では、どう対処するか?
一つの方法としてmethod_missing を利用することが考えられます。
次のコードをご覧ください。
lang
1class Myxml 2 def method_missing(name, *args) 3 puts "<#{name}>" 4 yield if block_given? 5 puts "</#{name}>" 6 end 7end 8 9builder = Myxml.new 10builder.html { 11 builder.body { 12 builder.h1 13 builder.pr 14 } 15}
これを実行すると、次の出力が得られます。
<html> <body> <h1> </h1> <pr> </pr> </body> </html>
Myxml クラスでは html(), body(), h1(), pr() といったメソッドを定義していませんが、その名前でメソッドを呼びだせています。
そして、それらしく タグが出力されています。
投稿2014/08/31 08:15
総合スコア22324
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
こんにちは。同じく、Ruby入門者です。
あるコードの中にメソッド定義をしていないのに
普段みない方法でputsでclass名.new.nameみたいな感じで出力していました。
とのことですが、その class名 のクラスを、仮にMyClass
とします。
また、おっしゃられている
普段みない方法
の反対に、「普段みる方法」を def ・・・end
と記述することでの
メソッド定義という前提のもとに回答します。
MyClassの中で、nameメソッドが、defを使って
lang
1def name 2 ・・・・ 3end
と定義されていなくても、
lang
1puts MyClass.new.name
で、MyClassオブジェクトのnameという属性を表示させることができるように
するコードの例として、もう1つ以下が挙げられます。
lang
1class MyClass 2 attr_accessor :name 3 4 def initialize 5 @name = "hello" 6 end 7 8end 9 10puts MyClass.new.name
上記を実行すると、
lang
1hello
と表示されます。
参考までに、以下は「メタプログラミングRuby」P.154からの引用です。
attr_accessor()のようなメソッドはクラスマクロと呼ばれる。クラスマクロは
キーワードのように見えるが、クラス定義の中で使える単なるクラスメソッドである。
投稿2014/09/02 22:22
総合スコア9058
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
もしかしてdefine_methodのことですかね
このメソッドだったら、クラスやモジュールにメソッドを定義して
defによるメソッド定義を使わなくてもメソッドを定義できますので。
詳しくはRubyのリファレンスでdefine_methodを調べていただければ
良いかと思いますよ。
投稿2014/08/31 06:53
総合スコア87
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。