質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Q&A

解決済

4回答

2176閲覧

Ruby メソッド定義せずにメソッドを定義する方法

shin8

総合スコア15

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

0グッド

0クリップ

投稿2014/08/30 13:58

Ruby初心者です。
あるコードの中にメソッド定義をしていないのに
普段みない方法でputsでclass名.new.nameみたいな感じで出力していました。
これは一体どういうことなのでしょうか?
どなたか何かご存知であれば教えてください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

ベストアンサー

ご質問の内容だけですと可能性はいくつも考えられます。

  1. クラスの継承や mix-in をしている
  2. オープンクラスとして他のファイルで定義してる
  3. define_method や eval などで定義してる
  4. 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

yohshiy

総合スコア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

katoy

総合スコア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

jun68ykt

総合スコア9058

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

もしかしてdefine_methodのことですかね

このメソッドだったら、クラスやモジュールにメソッドを定義して
defによるメソッド定義を使わなくてもメソッドを定義できますので。

詳しくはRubyのリファレンスでdefine_methodを調べていただければ
良いかと思いますよ。

投稿2014/08/31 06:53

yamaguchi79

総合スコア87

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問