koheitakahashiのブログ

2020.07.01にプログラマーとして生を受けた私が学んだことや、日常について徒然に書いていきます。

Rubyのクラスとは?モジュールとは?

fjordbootcampのRubyのプラクティスを進めていく中で、私はオブジェクト、クラス、モジュールの概念がよく理解することができませんでした💦

そこで、自分の知識を整理するために、自分なりにそれらについて調べたことをまとめていきたいと思います。

クラスとは?

Ruby プログラムからはクラスもまたオブジェクトとして扱うことができ、文による操作と合わせると以下の基本操作が可能です。 メソッドの存在を問い合わせる。 メソッドを定義する。 メソッドの定義を取り消す。

Ruby 2.6.0 リファレンスマニュアルより

という役割を持ちます。私としては、分かったような分からないような感じがしました。 そこで、クラスとは、たい焼きの型である!!と例えている記事がありました。

クラスは何かを実行するために必要な設計図と言われます。つまりは、たい焼きの型なのです。たい焼きの型は、たい焼きというものを作り出すために存在します。ただ、たい焼きの型だけあっても、たい焼きを作れたとは言えません。

インスタンスとは?

クラスから、作られた実体のことをインスタンスと言います。つまりは、たい焼きの型から焼きあがった、たい焼きのことをインスタンスと言います。

じゃあ、どうやってクラスを書いていくのか?

class クラス名
  式...
end

が基本となります。 例えば、たい焼きクラスを作る時は以下のようになります。

class Taiyaki
  attr_reader :nakami
  def initialize(nakami)
    @nakami = nakami
  end
end

一つ一つ説明していきます。

  • attr_reader :nakami 基本的に、インスタンス変数はクラス内からしか取得することはできません。そのため、クラス外から直接インスタンス変数を参照するためには、ゲッターと呼ばれるインスタンス変数を参照するための専用のメソッドを定義する必要があります。

例えば、

class Taiyaki
  def initialize(nakami)
    @nakami = nakami
  end
end

と記述して

class Taiyaki
  def initialize(nakami)
    @nakami = nakami
  end
end

taiyaki_1 = Taiyaki.new(あんこ)

オブジェクト(あんこが入ったたい焼き)を作ったとしても

puts taiyaki_1.nakami
=> #taiyaki.rb:8:in `<main>': undefined method `nakami' for #<Taiyaki:0x00007ff72e91b388 @nakami="あずき"> (NoMethodError)

では、値を返してくれません。 クラス外からのインスタンス変数を参照できないのです。

そこで、

class Taiyaki
  def initialize(nakami)
    @nakami = nakami
  end
  
  def getnakami
    @nakami
  end
end

クラス外からのインスタンス変数を参照するために、ゲッターを記述する必要があります。しかし、この方法には問題があり、多くのインスタンス変数がある場合には、ゲッターを定義するだけで一苦労です。

そこで、 attr_reader :変数名 と記述することで、一括して、そのクラスのインスタンス変数をクラス外から参照できるようにするのです。これをアクセスメソッドと呼びます。

  • def initialize(nakami) @nakami = nakami end

initializeは、クラスの初期化を行うメソッドです。さらに、自作のメソッドでinitializeを定義すると、privateを使わなくても自動的にprivateなメソッドになります。

ここで一つ疑問が私の中に生まれました。 「クラスの初期化をなぜ、行わなければならないのか?」

それは、手間を削減できるからです。どういう手間かと言うと、initializeを記述しないと、クラスを.newによりオブジェクト化して、それをインスタンスメソッドへ引数として渡さなければ、いけないのです(実は私もここら辺はあまり理解しておりません💦)。 一つの処理だけなら問題はないのですが、複数の処理があると、各処理ごとに毎回設定しなければならないので、それを一括で削減してくれるのがinitializeメソッドなのです。

そして、今回、initializeが初期化しているのは@nakamiです。 @nakami = nakamiはインスタンス変数と呼ばれます。 インスタンス変数とは何かというと、クラス内の全メソッドで共通したオブジェクトの値を保存しておくところです。インスタンス変数名は@で始まることとなっています。

そして、ここまででクラスを作成することができました。 クラスはたい焼きの型ですので、このままでは何の実体を持ちません。そこで、たい焼きを実際に作ってみる必要があります。

taiyaki_1 = Taiyaki.new('あずき')
puts taiyaki_1.nakami

taiyaki_2 = Taiyaki.new('白あん')
puts taiyaki_2.nakami

たい焼きの作成は、.newで行うことができます。 newメソッドは、クラスをインスタンス化して、いつでも使える状態にしておくメソッドです。つまりは、たい焼きがいつでも食べられるようにしておくものです。

今回は、中身が「あずき」のtaiyaki_1というたい焼きと、中身が「白あん」のtaiyaki_2というたい焼きを作成しました。

そして、putsでたい焼きとその中身が出力されるようになります。

これがクラスの定義からオブジェクト化までの流れです。

モジュールとは?

モジュールとは、クラスとよく似た性質を持ちますが、オブジェクトを作成することができません。また、クラスは継承することができますが、モジュールではできません。 クラスと違って不便なようにも見えますが、使用する目的としては以下のようなことが挙げられます。 - クラスやメソッドなどと名前が異なることによって、名前の衝突が起こらない。 - 同じ意図を持ったメソッドをまとめることができる。

モジュールは、以下のように記述します。

module モジュール名
end

モジュールを使用することによって、名前がかぶることなく、スマートな記述ができます。

とここまで、自分の学んだことをまとめてみました。稚拙な説明になってしまいましたが、現時点での私の理解度はここまでということで、ご容赦ください。 あとは、実際にプログラムを書いていく中で、理解度を深めていきたいと思っております🙇‍♂️

参考にさせていただいたサイト