LoginSignup
11
9

More than 1 year has passed since last update.

【やっとわかった】self.っていつ使うん?(実務コードから見たクラスメソッド、インスタンスメソッドの使い分け)

Posted at

はじめに

Rubyのコードでたまにself.nameみたいな感じでselfがついているコードをしばしば見かけるときがあります。Java、C#、Javascriptだとthisみたいなものですが、そもそもこのselfって「何を意味してるの?どんなときに使うの?」と疑問に思っていました。

今回Rubyの参考書でチェーリー本として有名なプロを目指す人のためのRuby入門を読んだのでメモとして残したいと思います。

self.っていつ使うん?という疑問

そもそも実際どこで使うの?という疑問がまずあったので企業のコードで探してみるとメソッドを定義する際に使用されていました。

class Fuga
  def self.hoge
    # 処理
  end
end

こんな感じ。def Fuga.hogeと書くこともできる。このメソッドをクラスメソッドと言うらしいです。
Rubyの公式リファレンスマニュアルには以下で記載されていました

Rubyにおけるクラスメソッドとはクラスの特異メソッドのことです。
特異メソッドとはクラスではなくある特定のオブジェクトに固有のメソッドです。

なるほど、意味わからん笑
クラスメソッドに関して色々と調べてみるとインスタンスメソッドと比較されることが多かったため次章ではインスタンスメソッドと比較しクラスメソッドに関して追求していきます。

インスタンスメソッドとクラスメソッドについて

まずクラスメソッドとインスタンスメソッドはなんぞや?と言う話なんですが、どちらもクラス内で定義するメソッドのことです。
じゃあこの二つは何が明確に違うのかと言うとインスタンスメソッドはインスタンス化したものに対して使用できるメソッド。クラスメソッドはクラスから呼び出す事ができるメソッドです。

# インスタンスメソッド
class User
  attr_accessor :name
  def initialize(name)
      @name = name
  end

  def hello
    puts "#{@name}さんこんにちは"
  end
end
========================
user = User.new('Alice')
user.hello #=> "Aliceさんこんにちは"

このdef helloがインスタンスメソッド
このようにインスタンスメソッドはインスタンス化したものに対し呼び出す事ができます。逆に言えばインスタンスでないものには呼び出す事ができません。

ちなみにRailsだとmodelとして定義しておけばActiveRecordが作用し、このattr_accessor :nameやinitializeして初期化する必要がなくnameを呼び出す事ができてしまいます。Rubyを学習していくといかにRailsが便利かが良くわかりますよね。

# クラスメソッド
class Aisatu
  def 
    puts "こんにちは"
  end
end
========================
Aisatu.hello #=> "こんにちは"

一方でクラスメソッドはクラスに対して呼び出す事ができるメソッドです。インスタンス化せずともメソッドを呼び出す事ができます。

そもそもクラスとインスタンスって何?

良く分かり易い例であるのがクラスは設計図の働きをしてインスタンスは実際に生成されたものと言うイメージ。実際の例は以下。

用語 例1 例2
クラス 車の設計図 たい焼きの型
インスタンス 実際の車 カスタードたい焼き

クラスメソッドを使う事はあるのか?

ここで自分は思いました。「基本インスタンス化したものにしかメソッドって使わなくないか?」と。Railsでもmodelでインスタンスメソッドを定義し、投稿フォームなどでcreateされたインスタンスに対しメソッドを呼び出す事がほとんどです。

チェリー本ではクラスメソッドの使い時を次のように記載していました。以下参照。

クラスに関連は深いものの、ひとつひとつのインスタンスに含まれるデータは使わないメソッドを定義したい場合もあります。
そのような場合はクラスメソッドを定義したほうが使い勝手が良くなります。

つまりどういう事か。クラスとの関連が深く、複数のインスタンスに対して処理したい場合はクラスメソッドとして定義するのが良いのではないだろうか。あとはインスタンスに含まれるデータ(カラム)を使用しないメソッド?(こっちはあんまりなさそう)。自分の中ではこういった仮説を立ててみました。

さて、この仮説をもとに改めて企業のコードを見てみました。すると仮説通り複数のインスタンスに対して処理をするメソッドをクラスメソッドとして定義しているコードが多かったです。
具体的な例としては

  • CSV出力のためのデータ加工としてデータを配列やハッシュに入れたりするメソッド
  • 複数のサイトのURLを加工する処理
  • scopeのような感じで絞り込みとして使用する

あとはそのクラスに関連する文字列を出力するクラスメソッドも中にはありました笑

ある程度クラスメソッドの使いどきに関して理解できた気はしました。今後クラスメソッドを作成するか否かはこれを指針にしていきたいと思います。

とここまできましたが、このチェリー本の作者の伊藤淳一さんがここら辺に関して記事にしていただいていました。

余談:selfについて

Rubyにおいてそもそもselfはなんだ?という話ですがインスタンス自身を表します。なのでインスタンスメソッド内でbinding.pryとかで止めデバックした際にselfと打つとインスタンス化したデータが取得できます。

# インスタンスメソッド
class User
  attr_accessor :name
  def initialize(name)
      @name = name
  end

  def hello
    binding.pry # ここで止めてみる
    puts "#{@name}さんこんにちは"
  end
end
========================
user = User.new("Alice")
[1] pry(#<Users>)> self
=> [#<User:0x00007f16b0af5398
  id: 1,
  name: "Alice"]
[1] pry(#<Users>)> self.name
=> "Alice"

こんな感じで取れます。しかしRubyでは基本的にselfを省略(nameだけでも)してもインスタンスメソッド内では値が取れるのでselfは省略される事がほとんどです。

あとがき

いかがだったでしょうか?今回はself.っていつ使うん?という疑問からクラスメソッド、インスタンスメソッドの使い分けにまで発展し記載してみました。

ここら辺ってほんとこんがらがりますよね。調べるたびにどんどん訳わかんないワードが出てきて大変です笑 そこをめんどくさがらず丁寧に調べていける人が良いエンジニアになれるんだろうなーってつくづく思わせられました。

最後までご覧いただき本当にありがとうございました!!
少しでも良かったと思っていただけたらLGTMポチッといただけますと幸いです。

Twitterでも日頃の業務で思ったことを呟いていくのでご覧いただけると幸いです。
@mokio_50

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9