Ruby のメソッドについてお教え下さい。


下記のようなプログラム deftest.rb があります。
1: #!/usr/bin/env ruby
2: def deftest (str)
3: str.gsub!("yamada", "sato")
4: end
5: name="yamada taro"
6: p deftest(name)
7: p name.deftest

プログラムを実行すると,下記のようにプログラムの7行目でエラーになります。

$ ruby deftest.rb
"sato taro"
deftest.rb:7:in `<main>': private method `deftest' called for "sato taro":String (NoMethodError)

【質問】
・p name.deftestのメソッド呼び出し方で,"sato taro"と出力させるためには,2行目〜4行目の def deftest 〜 end をどのように記述すれば宜しいでしょうか。

回答の条件
  • 1人5回まで
  • 登録:
  • 終了:2013/05/30 14:39:29
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:a-kuma3 No.2

回答回数4973ベストアンサー獲得回数2154

ポイント290pt

ちょっと無理矢理ですけど、こんな感じ。

#!/usr/bin/env ruby

def deftest (str = nil)
    unless str.nil? then
        str.gsub("yamada", "sato")
    else
        self.gsub("yamada", "sato")
    end
end

name="yamada taro"
p deftest(name)
p name.deftest

引数が nil の場合には、self を対象にするようにしてます。
引数無しで呼び出したときには、やっぱりエラーになっちゃうので、デフォルト引数の指定もしました。
無理矢理感が伝わるでしょうか?

トップレベルにメソッドの定義をすると、スコープ的にはどこからでも呼び出せますが、対象となるオブジェクトがあいまいになってしまいます。
あくまで、非OO な言語の関数やサブルーチンとして使う方が良いでしょう。


それとも、こちらの方が良いでしょうか。

#!/usr/bin/env ruby

def deftest str
    str.gsub("yamada", "sato")
end

class String
    def deftest
        gsub("yamada", "sato")
    end
end

name="yamada taro"
p deftest(name)
p name.deftest

実装が散らばるのも、気持ち悪いんだよなあ...


後、引数の変数を破壊するのは、どうかなと思って、gsub! → gsub にしてますが "yamada taro" の内容を破壊して良いのであれば、両方とも破壊的なメソッドを使ってください。



追記です。

二番目の書き方は、やっぱり気持ち悪いよなあ、と思ってたら、こんなのを見つけた。
http://www.antimon2.atnifty.com/lab/2010/05/ruby-memo-method.html
http://www.antimon2.atnifty.com/lab/2010/11/ruby-memo-method-2.html

というわけで、こんな感じが一番すっきりするのかも。

#!/usr/bin/env ruby

def deftest str
    str.gsub("yamada", "sato")
end

class String
    def deftest
        Kernel.send(:deftest, self)
    end
end

name="yamada taro"
p deftest(name)
p name.deftest
id:goto_hirosi

一番最後に記載して頂いたソースコードを使用させて頂きます。
記載されたURL 先内容も参考にさせて頂きます。

大変助かりました。有り難うございました!

2013/05/30 14:38:18

その他の回答1件)

id:taknt No.1

回答回数13539ベストアンサー獲得回数1198

ポイント10pt

http://doc.ruby-lang.org/ja/1.9.3/doc/spec=2fdef.html
メソッド定義式内で呼べるそうです。
なので メソッド定義式を作ってそれから呼び出すようにしましょう。

id:goto_hirosi

ご回答有り難うございます。具体的なソースコードでご回答頂けると助かります。

id:a-kuma3 No.2

回答回数4973ベストアンサー獲得回数2154ここでベストアンサー

ポイント290pt

ちょっと無理矢理ですけど、こんな感じ。

#!/usr/bin/env ruby

def deftest (str = nil)
    unless str.nil? then
        str.gsub("yamada", "sato")
    else
        self.gsub("yamada", "sato")
    end
end

name="yamada taro"
p deftest(name)
p name.deftest

引数が nil の場合には、self を対象にするようにしてます。
引数無しで呼び出したときには、やっぱりエラーになっちゃうので、デフォルト引数の指定もしました。
無理矢理感が伝わるでしょうか?

トップレベルにメソッドの定義をすると、スコープ的にはどこからでも呼び出せますが、対象となるオブジェクトがあいまいになってしまいます。
あくまで、非OO な言語の関数やサブルーチンとして使う方が良いでしょう。


それとも、こちらの方が良いでしょうか。

#!/usr/bin/env ruby

def deftest str
    str.gsub("yamada", "sato")
end

class String
    def deftest
        gsub("yamada", "sato")
    end
end

name="yamada taro"
p deftest(name)
p name.deftest

実装が散らばるのも、気持ち悪いんだよなあ...


後、引数の変数を破壊するのは、どうかなと思って、gsub! → gsub にしてますが "yamada taro" の内容を破壊して良いのであれば、両方とも破壊的なメソッドを使ってください。



追記です。

二番目の書き方は、やっぱり気持ち悪いよなあ、と思ってたら、こんなのを見つけた。
http://www.antimon2.atnifty.com/lab/2010/05/ruby-memo-method.html
http://www.antimon2.atnifty.com/lab/2010/11/ruby-memo-method-2.html

というわけで、こんな感じが一番すっきりするのかも。

#!/usr/bin/env ruby

def deftest str
    str.gsub("yamada", "sato")
end

class String
    def deftest
        Kernel.send(:deftest, self)
    end
end

name="yamada taro"
p deftest(name)
p name.deftest
id:goto_hirosi

一番最後に記載して頂いたソースコードを使用させて頂きます。
記載されたURL 先内容も参考にさせて頂きます。

大変助かりました。有り難うございました!

2013/05/30 14:38:18

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません