🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Ruby

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

Q&A

解決済

2回答

749閲覧

練習問題を解く際クラスメソッドやモジュールで実装する理由が知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

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

0グッド

2クリップ

投稿2021/01/04 08:22

編集2021/01/05 02:47

プログラミングの初心者です。
最近このページを見て練習をしています。
いくつか問題に取り組み筆者の回答を見たとき一つ疑問に思ったことがあります。
それは実装の方法です。

殆どの問題はクラスメソッドとして実装されていますが、この行単位、列単位で合計値を求めるという問題はモジュールで実装されています。

簡単な練習問題をクラスメソッドで実装する利点(トップクラスでメソッド定義したりすればいいのでは)、またクラスメソッドでなくモジュールで定義する利点を教えてください。

#(追記)
###1,カレンダー作成問題
この問題に関連付けられた回答ではないですがこのページに筆者の回答がありました。こちらはインスタンスメソッドでした。
###2,カラオケマシン問題
回答テンプレートではインスタンスメソッドでした。
###3,ビンゴカード作成問題
CodelQのページが残っていませんがこのページから回答テンプレートでクラスメソッドが指定されていることがわかります。
###4,ボーナスドリンク問題
回答テンプレートではクラスメソッドでした。
###5,電話帳作成問題
回答テンプレートではクラスメソッドでした。
###6,国民の祝日.csv パースプログラム
このページではクラスメソッドでした。
###7,「Rubyで英語記事に含まれてる英単語を数えて出現数順にソートする」問題
このページでは呼び出し部分がクラスメソッドで処理部分はインスタンスメソッドです。
###8,行単位、列単位で合計値を求めるプログラム
このページではモジュールでした。
###9,ガラケー文字入力問題
筆者の回答がありませんでした。
###10,値札分割問題
筆者の回答ではメソッドでした。

##結果
5割がクラスメソッド、2割がインスタンスメソッド、1割がモジュール、2割がその他
となりました。

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

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

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

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

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

ockeghem

2021/01/05 01:21

「殆どの問題はクラスメソッドとして実装されています」ということですが、そのような解答のURLを教えて下さい。
退会済みユーザー

退会済みユーザー

2021/01/05 02:45

追記しました。
guest

回答2

0

簡単な練習問題をクラスメソッドで実装する利点(トップクラスでメソッド定義したりすればいいのでは)

トップレベルのインスタンスメソッドにするには使用が限定的であるので不適切であるというのが一番大きな理由だと思います。それと副産物的なものですが、定義したメソッド群に対してわかりやすく名前をつけているとかでしょうか。

またクラスメソッドでなくモジュールで定義する利点を教えてください。

メソッドが関数的に使われているのでRubyっぽくはないですね。特に利点があるとも思いません。
クラスを定義して generate_matrix の処理なんかは少し改良して initialize でやるとRubyっぽくなるかなと思います。


リンク先の記事の主旨は「Ruby力の向上」のようなので、あえて普段しないような書き方をしたのかもしれません。そうでなくとも今回の質問者さんのように疑問を感じて調べるきっかけとなったのであればそれはそれでとても有意義なものだと思います。

投稿2021/01/05 02:33

編集2021/01/05 03:27
Mugheart

総合スコア2349

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

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

退会済みユーザー

退会済みユーザー

2021/01/05 03:10

回答ありがとうございます! 「selfをextendしているのでトップレベルでモジュールを定義している場合、トップレベルのメソッド定義とほとんど同義」とはどういう事でしょうか。解説して頂きたいです。
Mugheart

2021/01/05 03:20

あぁ、ごめんなさい全然違うこと言ってます。上のコメントは無視してください。
Mugheart

2021/01/05 03:25

module 内での extend self はそのモジュールをどこかのクラスやトップレベルで include 等することなく関数的に定義したメソッドを使用できるための記述です。 ですので「selfをextendしているのでトップレベルでモジュールを定義している場合、トップレベルのメソッド定義とほとんど同義」は誤りです。忘れてください。 > トップクラスでメソッド定義したりすればいいのでは これがその通りで、あえてモジュールを定義した理由があるとするならば「トップレベルのインスタンスメソッドにするには使用が限定的であるので不適切」なのと「定義したメソッド群に対してわかりやすく名前をつけている」が正しい回答でした。回答も修正しておきます。
退会済みユーザー

退会済みユーザー

2021/01/05 05:00

なるほど、何回も使うわけではなく一つのケースにつき一回一連の流れを行うので、モジュールとしてまとめたということですね。 回答ありがとうございました。
Mugheart

2021/01/05 05:36

> 何回も使うわけではなく一つのケースにつき一回一連の流れを行うので、モジュールとしてまとめた うーん、違います。トップレベルにメソッドを定義すると、どこからでも呼び出せるメソッドになってしまうのでスコープが広すぎるのです。プログラムを書く上であらゆるもののスコープはできるだけ狭くする方が好ましいとされているので、そういった意味でトップレベルへのメソッド定義を避けているのだと思います。 解答例のようにモジュールに対してメソッドを定義することで、そのモジュールをレシーバとしたメソッド呼び出しでのみ呼び出しが可能となるので、スコープも限定的で競合が起きるリスクも少ないのです。
退会済みユーザー

退会済みユーザー

2021/01/05 05:53

ありがとうございます。
guest

0

ベストアンサー

「殆どの問題はクラスメソッドとして実装されています」
これ本当ですか?
「クラスを定義し、そのインスタンスメソッド」ではないですか?
クラスメソッドとして実装 ですと、クラスを作る意味が殆ど無い、トップレベルでメソッド定義したほうが(このくらいの複雑さの少ない)問題ならよいと思います。

クラスかモジュールか、は考え方の違いでどちらが良いか悪いかということは余りないと思います。
クラスは「自分で解かせる」methodは問題固有で他に流用は考えない
モジュールは「他に委ねる」methodは汎用性があり、他のテーマにも使える
という感じでしょうか。
ただ、引用している「モジュールでの解き方」は参考にするようなものとは思えません。不必要に複雑。
この問題はクラスを作ることもなく、1行野郎です。

追記
全部の例を読んで考察するほどのテーマではないと思うので、たまたま開いた「電話帳作成問題」について。
これも含めあのようなサイトでは自動で評価します。何も指定しないと呼び方がまちまちになり自動評価にかけるのが出来ないので、プログラムをどう呼ぶかを規制します。「電話帳作成問題」ではNameIndex.create_index(names)と呼ぶよ、ということを宣言しています。
で、
classで作る以上、入り口はclassメソットにせざるを得ません。実装を全部classメソッドで書けと言っているわけではないですし、もしそうしたら object指向でのプログラムとしては減点されるでしょう。
私もこういう書き方をすることはよくあります。
class CsvIo def self.create(data) new(data).make end def make ごちゃごちゃ end end
みたいな感じ。classメソッドでインスタンスをつくる。実際の仕事はインスタンスが行う。

「methodは汎用性があり、他のテーマにも使える」 の意味は、組み込まれているmodule Mathのメソッドの使い方を見ればわかるのでhあないか、と。

投稿2021/01/04 23:56

編集2021/01/05 04:05
winterboum

総合スコア23567

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

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

退会済みユーザー

退会済みユーザー

2021/01/05 03:06

追記しましたが半分がクラスメソッドとして実装されていました。 「クラスは「自分で解かせる」methodは問題固有で他に流用は考えない モジュールは「他に委ねる」methodは汎用性があり、他のテーマにも使える」 について、よく理解ができないので詳しく解説して頂きたいです。
退会済みユーザー

退会済みユーザー

2021/01/05 05:24

そのような理由があったんですね、全く思い当たりませんでした。ありがとうございました。 モジュールの汎用性については、クラスメソッドはレシーバ付きで呼び出しクラス内部で処理処理するだけだが、モジュールはインクルードやエクステンドができる、ということでしょうか?
winterboum

2021/01/05 06:54

はい、それが一番の違いですね。 ただ、Math.sin() みたいにちょくに呼ぶこともできます。
退会済みユーザー

退会済みユーザー

2021/01/05 07:45

回答ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問