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

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

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

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

Q&A

解決済

2回答

1128閲覧

クラスメソッドとインスタンスメソッドの使い分け

mika2002

総合スコア20

Ruby

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

0グッド

1クリップ

投稿2020/05/08 02:12

クラスメソッドとインスタンスメソッドについて、検索して色々と読んでいたのですが書き方の違いはわかっても、その使い分けについて、はっきりとわかりませんでした、、

クラスメソッドはそのクラス全体に関するものを変更する?ときにつかい、インスタンス変数は生み出したインスタンス(carクラスがあれば、honda-carとか?)を変更する際に使う、というようなイメージなのかなーと思ったのですが、これがあっているかもわからないし、実際の開発ではどのように使い分けるのかな、と疑問に思いました。

どなたか例を交えて教えて頂けると、大変嬉しいです。

よろしくお願いします!

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

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

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

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

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

guest

回答2

0

ベストアンサー

クラスメソッドとは「クラスオブジェクトから実行可能なメソッド」です。
※クラスメソッドはクラスをレシーバ(.の左側)として呼び出すメソッドでもあります。

またインスタンスメソッドについてはクラスに対してではなく、「クラスのインスタンス(実体)」に対して紐づけられるメソッドです。

こちらのページに記載があります。
https://www.sejuku.net/blog/19208

補足で説明をすると、

# クラスメソッド # クラスであるHomeが持っているメソッド(self.pc)を呼び出して実行。 # つまりクラス自身が実行できるメソッドがクラスメソッドと言えます。 class Home def self.pc print("Personal Computer") end end Home.pc
# インスタンスメソッド # Japaneseクラスを.newでインスタンス化したinstanceが、 # Japaneseクラスの持っているメソッド(nagase)を呼び出して実行。 # つまり、クラスのインスタンスが実行できるメソッドがインスタンスメソッドです。 class Japanese def nagase print("Nagase Rai") end end instance = Japanese.new instance.nagase

簡単に言えば、
・レシーバー(.の左側)がオブジェクト(インスタンス)の場合はインスタンスメソッド。
・レシーバーがクラスの場合はクラスメソッド。
となります。

クラスメソッドはインスタンスを作成する時に使用されるというのは、
例えば新しく配列を作る場合には、

array = Array.new

のように書きますが、この「Array.new」などもArrayクラスがnewというクラスメソッドを呼び出して配列のインスタンスを作成し、arrayへ代入する流れになるので、インスタンス作成に使われると言われているのだと思います。

そして、作られたarrayインスタンス変数が使用できるメソッドがインスタンスメソッドなわけです。

どちらのメソッドも、Arrayクラスが持っている事になりますが、クラスが呼び出せるもの、インスタンスが呼び出せるもので使うタイミングが異なりますので状況に応じてどちらを使うかが変わってくるわけです。

投稿2020/05/08 05:59

gnfreeworks

総合スコア306

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

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

mika2002

2020/05/09 08:19

ご回答ありがとうございます! 初心者なこともあって、少し理解するのに時間がかかってしまい、申し訳ございません、、 `array = Array.new` の部分が、 Arrayクラスがnewというクラスメソッドを呼び出している。という説明もすごくしっくり来ました! ただ、そういったパターン以外で、 同じクラスの中に、 ```ruby class 〇〇 def self.△ end  def xxx end end ``` といったようにクラスの中の△はクラスメソッドで、☓はインスタンスメソッドで、という風に使い分けるときがあるかと思います。 そのような場合は、その使い分けは例えばどういったケースがあるのかをお聞きできると嬉しいです、、 追加ですみませんがよろしくお願い致します。
gnfreeworks

2020/05/09 09:50

私もまだ勉強中の身でうまく説明が出来ませんので、 少し古いですがこちらの記事が参考にしてみて下さい。 https://blog.mah-lab.com/2014/11/13/instance-method-and-class-method-with-ruby/ 使い分けというよりは、まずインスタンスメソッドで実現できないか?を考えるべきだそうです。 インスタンスメソッドの方が良い場合と、クラスメソッドの方が良い場合は何がしたいかでクラス設計が変わってきます。 上記のWebサイトでは、インスタンスメソッドで実装すべき処理をクラスメソッドで作り変えた場合の例が載っていますが、呼び出し時に渡す引数の数が増えて扱いづらくなっていくのが分かります。 どちらの作り方が正しいということは無くどの書き方でも同じ処理を実現出来るので、まずはインスタンスメソッドで実装してみて、そこからリファクタリング(処理内容を変えずに効率的なコードへ書き換える)を行えば良いと思います。 その結果、mika2002さんの例のように同一クラス内にクラスメソッド、インスタンスメソッドの両方が存在する方が一番簡略化されるのであればそれで良いと思います。
mika2002

2020/05/10 05:32

ありがとうございます! 教えていた記事を読んだのですが、少しだけ認識があっているかお聞きしてもよろしいでしょうか? こちらのような書き方を初めて見たのですが、 ```ruby def initialize(title, body) @title, @body = title, body end ``` これは、引数である、 title, bodyが@title, @body にそれぞれ代入されている、ということですよね。。? そして、このinitializeメソッドがあるから、 ` Post.new(title, body)` こちらのnewをするだけで、自動的にinitializeメソッドが呼び出されて?titleとbodyが渡される。 (このiinitializeメソッドはクラスメソッドでは使用できない?) 結果、 puts post.render とするだけで、呼び出すときに引数なしで、簡潔に ```ruby def render <<-EOS <article> <h1>#{@title}</h1> <p>#{@body}</p> </article> EOS end ``` と表示まで行えるのに対して、 クラスメソッドでは、iinitializeメソッドがない為、 `puts Post.render('タイトル', '記事の内容')` としないといけない。 という形でしょうか、、 長くなってしまい申し訳ないのですが、教えて頂けると大変嬉しいです。 よろしくお願い致します。
gnfreeworks

2020/05/10 09:46

そのような認識で合ってると思います^^ クラスメソッドの場合は、.newでインスタンス化しないのでinitializeメソッドが呼び出せません。 そうするとインスタンス変数が作成できないので.newをした際に初期化で渡した値をクラス内で管理出来ず、外部の変数へその結果を保管することになります。 結果、インスタンスメソッドは使いたい時に「post.render」だけで呼び出せますが、 クラスメソッドは使いたい時には必ず引数を渡す形になります。 ※クラスメソッドでも引数を必要としないものもあるので必ず引数が必要というわけではありませんが、 値を渡して処理をさせるというクラスを作る場合はクラスにデータを保管出来ないので ちょっと不便になるかもしれませんね。
mika2002

2020/05/10 13:03

ありがとうございます!! わかりやすい説明で、すごく勉強になりました。。
guest

0

インスタンスメソッド→そのインスタンスの属性を参照・変更するなど、個々のインスタンスの状態によって結果が変わる処理
クラスメソッド→個別のインスタンスには関係がないけどクラス横断的に関係のある処理

投稿2020/05/08 04:18

gentaro

総合スコア8949

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

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

mika2002

2020/05/08 04:57

ありがとうございます!! ただ、「クラス横断的に関係のある処理」が例えばどういったものなのかが、わからないので、こちらも教えて頂けると嬉しいです、、 質問させていただいた後も、 使い分けについて https://qiita.com/hogeta_/items/27221675638cdc9bde6b#%E3%82%AF%E3%83%A9%E3%82%B9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%A8%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%BF%E3%83%B3%E3%82%B9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%AE%E4%BD%BF%E3%81%84%E5%88%86%E3%81%91 こちらの記事を読んだりしていたのですが、 > クラスメソッドとインスタンスメソッドの使い分け この辺りはクラス設計のお話なのでなかなか難しいところで、意見が分かれるかもしれないので あくまで一個人の考えとして捉えてください。 基本的にはインスタンスメソッドで全てまかなってみるというのが根本的思想のように思います。 では、クラスメソッドはいつ使えばいいのかですが、これは 新しいインスタンスを生成するときに使われることが多い印象です。 単純なwhereやfindでは作れない複雑な条件を書くときはクラスメソッドで記述して、 それをコントローラで呼び出すということがよく行われている気がします。 という風にありました。 この、「クラスメソッドはいつ使えばいいのかですが、これは 新しいインスタンスを生成するときに使われる」の部分の意味がわかりません。 こういったところを理解しておきたいです。 長々とすみません、、 よろしくお願いします
gentaro

2020/05/08 06:01 編集

その記事を書いた人がどういう考えなのかは本人に聞かないとわかりませんが、例えばWhereやFindというメソッドがコレクションを表すインスタンスが持つものであれば、そのコレクション(インスタンス)が保持する個々のオブジェクトを検索することになります。そのため、XXXコレクションクラスのインスタンスメソッドとなります。 コレとは違い、例えばDBやその他ファイルからUserというクラスのインスタンスを検索条件に従って生成したい場合、User.GetById(int)みたいなクラスメソッドを実行し、特定のUserクラスのインスタンスを生成して返すメソッドを作ったりします。 このメソッドはUserクラスに関連しているものの、個々のインスタンスそのものとは結びつかない操作なので、クラスメソッドとするのが適切です。
mika2002

2020/05/09 14:43

すみません、、 一段落目が難しくて、、 コレクションを表すインスタンス とは、例えばどういったものの事でしょうか? またお時間のあるときに教えて頂けると幸いです、、
gentaro

2020/05/09 14:51

二段落目以降がわかっているのであれば、クラスメソッドに該当しない=インスタンスの持つ情報にアクセスする必要がある場合はインスタンスメソッドだ、という事だけ理解できれば良いです。
mika2002

2020/05/09 15:32

わかりました! 有難うございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問