プログラミング備忘録

プログラミングの学習状況をメモしています

36日目

今日の学習

Ruby

クラスメソッドとインスタンスメソッド

まだまだこの二つへの理解が浅いので、再び学習。

二つがそれぞれ出来ること自体は分かるし、別物だと感じることもできているのだが、クラスメソッドを使用する場面がやはり思いつかない。

クラスに使えるメソッドということは分かるのだが、使い道が分からないと「じゃあ具体的にはいつ使うのか、モジュールのextendはいつすればいいか」の検討がつけられない。

【Ruby】 たい焼きで理解するオブジェクト指向におけるクラスの概念 | Pikawaka - ピカ1わかりやすいプログラミング用語サイト

【Ruby入門】クラスメソッドとインスタンスメソッドの使い方まとめ | 初心者向け完全無料プログラミング入門

上記のサイトを参考に、もう一度学習してみた。

  • インスタンスメソッド
    インスタンスごとに保持している情報を使って処理を書くことができる
    インスタンスごとに異なる結果となる

  • クラスメソッド
    インスタンスの持つデータを使う必要のない処理は、クラスメソッドで定義
    クラス全体に関わる情報を変更したり 参照したりするメソッドを作成するときに使う

「〜のための」という言葉を付ければ分かりやすい気がする。

インスタンスのための」メソッド。

「クラスのための」メソッド。

moduleextendを使うときは、クラス全体に対して使用したいメソッドがある場合だと捉えると何となく分かったような。

モジュール

includeとextend

どうしてここまでクラスメソッド、インスタンスメソッドをはっきりさせようと思っているかというと、Ruby本でmoduleを活用する例題にextendが出てきたからだ。

なぜincludeではなくextendを使うのかの理由としては、「クラス構文の直下でモジュールのメソッドが呼ばれているため、クラスメソッド(特異メソッド)としてミックスインする必要があるから」と書かれている。

この言葉で混乱したが、includeが使用されているRuby本の例文を見てみると、クラスの中にあるメソッドの中で使われていることが分かった。

一方で、例題のモジュールはクラスの中にあるメソッド内で使われているのではなく、クラスの中でいきなり使われている。

クラスメソッドとしてミックスインする必要があるというのは、扱うモジュール自体をクラスのメソッドとしたい場合だという解釈に辿り着いた。

例となるコードを書いていないせいで、上記の文章だけだと分かりづらいだろうが、Ruby本のコードを丸写しというわけにもいかないので、出来るだけ後から見直しても分かるような書き方を心がけた。

名前空間

6日目で、よく見るとすでにモジュールについて学習していたようだが、書いてあることを見るに全く本質が掴めていない。

名前空間というものも、この時うっすらと検索した記憶があるのだが、Ruby本で改めて学習をした。

一人で全体を把握した上でプログラミングをする分にはいいが、大規模な開発や、複数人で作業をしていると、知らずのうちにクラス名が重複してしまう可能性がある。

Ruby本では、「野球の二塁手」という意味のSecondクラス、「時計の砂」という意味のSecondクラスを例に説明されていた。

このクラスは、定義されている中身は違うかもしれないが、Second.newで新しくインスタンスを作成しようにも区別がつかない。

この問題を解決するためのものが名前空間だ。

名前空間は、モジュール構文を用いて定義をすることで、名前の衝突を防ぐことが出来る。以下、Ruby本から大まかな抜粋。

モジュール構文の中にクラス定義を書くと、「そのモジュールに属するクラス」という意味になるため、同名のクラスがあってもモジュール名が異なっていれば名前が衝突しなくなる。

# 「野球の二塁手の」Secondクラス
module Baseball
  clas Second
  ...
   end
end

# 「時計に関する」Secondクラス
module Clock
  class Second
  ...
  end
end

上記クラスからインスタンスを新しく作りたい場合は、モジュール名::クラス名として、モジュール名とクラス名を区切って表記する。

Baseball::Second.new

Clock::Second.new

6日目の学習のときは、そもそも色々な用語の理解ができず、全然意味が分からなかったが、今はちゃんと理解できる。というか、Ruby本が非常に分かりやすいからだ。

名前空間は、クラス名の衝突を防ぐ以外にも、クラスのグループ分け、カテゴリ分けを目的に使われることもあるようだ。

prepend

モジュールは、prependを使ってミックスインすることができる。

includeとの違いは、prependでミックスインされたモジュールにあるメソッドは、ミックスイン先のメソッドよりも先に呼び出される。

includeを使用した場合

module A
  def hello
    puts "よろしく。こんにちは!"
  end
end

class Greeting
  include A

  def hello
    puts "こんにちは!よろしく。"
  end
end

greeting = Greeting.new
greeting.hello
#=> こんにちは!よろしく。

クラス内にあるhelloメソッドが優先されている。

prependを使用した場合

module A
  def hello
    puts "よろしく。こんにちは!"
  end
end

class Greeting
  prepend A

  def hello
    puts "こんにちは!よろしく。"
  end
end

greeting = Greeting.new
greeting.hello
#=> よろしく。こんにちは!

includeのときと違い、prependを使用することによってモジュールのhelloメソッドが優先されていることが分かる。

こうすることで、置き換えたい既存メソッドを置き換えることができる。

Ruby on Rails

Railsチュートリアルを無料で完走するはずが、現在有料版の第6版で学習していたことに気づいた。

Rails5.1の第4版は無料で閲覧できるようだが、新しくRailsのバージョンを下げたり、アプリを作り直す必要があることを考えて少し気が重くなってしまった。

自分はRails6.1を使用しているが、古いバージョンの学習も一応やっておいて損はないかも知れないので、明日以降挑戦したい。

PostgreSQLでエラー

rails newでアプリを生成して、まず初めにrails db:createをするとしょっぱなからエラーが出た。

could not connect to server: No such file or directory
        Is the server running locally and accepting
        connections on Unix domain socket "/tmp/.s.PGSQL.5432"?
以下略

Postgresで発生したエラー「PG::ConnectionBad: 〜"/tmp/.s.PGSQL.5432"?」に対処した - Qiita

エラー文などで検索してみると、似たようなエラーに見舞われた方の記事を発見。

postgres -D /usr/local/var/postgresを実行したエラーも同じ。

というわけで、この記事通りにpostmaster.pidを削除&postgresの再起動をすると、正常に動作するようになった。深謝。

学習メモ