プログラミング備忘録

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

32日目

今日の学習

Ruby

クラス

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

クラスメソッドインスタンスメソッドと違い、privateキーワードの下で定義してもprivateメソッドにならないが、そもそもこの二つのメソッドはどう使い分けるんだったか...となったので、改めて学習しようと思った。今まで意図的にクラスメソッドを作成したことがないのだ。

過去の記事にしれっと書いているが、「結局何?」という感じになってしまったので。

メソッドとクラスメソッドとインスタンスメソッドが曖昧だった - Qiita

こちらの説明と、記事にあるイメージ図が分かりやすかった。

class Greeting
  def japanese(name)
    puts "#{name}さん、こんにちは"
  end
end

japanese("長谷川")

これで実行してみると、

undefined methodjapanese' for main:Object (NoMethodError)`

そんなメソッドはない!と言われてしまう。

自分がクラスに含まれるメソッドを使う場合は、いつもインスタンスメソッドの形で使っているので、その形式でやってみる。

class Greeting
  def japanese(name)
    puts "#{name}さん、こんにちは"
  end
end

greeting = Greeting.new
greeting.japanese("長谷川")

#=> 長谷川さん、こんにちは

.Newを使ってインスタンス(greeting)を作成する。いつもならinitializeメソッドを使用して、インスタンス作成時に情報を付与することが多い。

その後、作成したインスタンスに対して、クラスにあるメソッドをつけるという形だ。

インスタンスメソッドを使用するには、インスタンスを作成しなくてはならない。

クラスメソッドはどうやらそうではないらしい。

class Greeting
  # クラスメソッドとして使用したいメソッドに、[self.]をつける!
  def self.japanese(name)
    puts "#{name}さん、こんにちは"
  end
end

# クラスそのものに対してメソッドで呼び出す
Greeting.japanese("長谷川")

#=> 長谷川さん、こんにちは

書き方にかなり違いがあるが、出力される内容は同一になった。

手軽にメソッドを呼び出したい場合は、クラスメソッドの方が楽だなと感じた。

が、結局どのような使い分けをすればいいのか?

クラスメソッド、インスタンスメソッド。いつ使うのか。 - Qiita

インスタンスメソッドの場合は、インスタンスごとで異なる動作をしたいときに使用して、クラスメソッドの場合は、クラス全体で共通の動作を行うときに使用するとのこと。

クラスメソッド : 全体

インスタンスメソッド : 個々

確かに、インスタンスメソッドは、しっかりと情報を与えてから使うイメージがある。

適材適所なことは分かるのだが、今の自分にしっかり線引きして使い分けができるかどうかと聞かれるとNOになる。

個人的にはオブジェクト指向に対してそこまで拒否感はないつもりなのだが、やはりまだまだ理解できていないということなんだろう。

上の記事の例では、学校のクラスを作成し、全校生徒の管理はクラスメソッドで。各教室の先生や生徒に関してはインスタンスメソッドで管理をしていて、イメージ自体は掴むことができた。

インスタンスインスタンスオブジェクトであり、それに使うメソッドなのでインスタンスメソッド

クラスはクラスオブジェクトであり、それに使うメソッドなのでクラスメソッド

こうして言葉にすれば当たり前だろうと言われそうなことだが、どうもRubyは全てが等しくオブジェクト!という考え方が自分に定着していないため、上のような書き方に気づいて今更「なるほど!」となってしまった。

クラス変数

先ほど貼った記事や、たまに目にする@@を先頭につける変数。これはクラス変数と言うらしい。

@をひとつだけつけて、インスタンス変数として使用しているが、これも先ほどのクラス/インスタンスメソッドと同じく、使い方が違ってくるのだろう。

【まとめ】インスタンス変数、クラス変数、クラスインスタンス変数 - Qiita

メソッドのときと同じく、インスタンス変数インスタンスごとに独立して値を持つことができるが、クラス変数クラス全体で共有される変数のようだ。

インスタンス変数は、クラスメソッドからはアクセスできないようだ。なぜ...?と思ったが、initializeメソッドオブジェクトのインスタンスメソッドしかアクセスできないかららしい。

さらにクラスインスタンス変数なるものがあるようだ。ぱっと見てもすぐ理解できなかったので、今回はとりあえずクラス変数の理解に努める。

インスタンス変数に値が入るのはインスタンス生成時だが、クラス変数の場合はクラス内で定義するため、最初から変数に値が入っている。

自分がこれまでに見かけたクラス変数の使い方は、クラスの中にあるものを数えたりするときだ。

やんばるエキスパート教材 | 八百屋プログラム(クラス)part3

ここでは、@idというインスタンス変数に、@@countというクラス変数を代入している。

class Student
# 1から順番に@idを振っていく
  @@count = 0

# initializeの中で定義することで、インスタンスを生成するたびに@idに+1されるようにする

  def initialize(name)
    @id = @@count += 1
    @name = name
  end

  def introduce
    puts "ID:#{@id}#{@name}です。"
  end
end

student1 = Student.new("長谷川")
student2 = Student.new("田中")
student1.introduce
student2.introduce

#=> ID:1、長谷川です。
#=> ID:2、田中です。

initializeメソッドに含めなくても、このメソッドを使った時に数を増やしたい、という場合には、そのメソッド内に数が増えるような処理を書くとよい。

このような限定的な使い方だけではないと思うが、とにかく使い方から覚えていって、どんどん応用できるようにしたい。

クラスメソッドをprivateメソッドにする

違いがそれとなく分かったところで、冒頭の「クラスメソッドインスタンスメソッドと違い、privateキーワードの下で定義してもprivateメソッドにならない」に戻る。

クラスメソッドをprivateメソッドで使いたいときは、class << self構文を使用する。

class Animal
  class << self
    #この中でならprivateキーワードで定義が可能になる
    private

    #このメソッドはクラス内でしか使えない
    def hello
      puts "hello"
    end
  end
end

もしくはprivateキーワードよりも手前に書き、後からprivate_class_methodでprivateメソッドに変更することができる。

上の例で言えば、まず普通にhelloメソッドを定義した後に、以下のようにする。

private_class_method :hello

private :hello

protectedメソッド

こちらのメソッドは使ったことがない。

Ruby本によると、「そのメソッドを定義したクラス自身と、そのサブクラスのインスタンスメソッドからレシーバ付きで呼び出せる」メソッドらしい。

使い所としては、「外部には公開したくないが、同じクラスやサブクラスの中であればレシーバ付きで呼び出したい」シーンで使うようで、Ruby本にある例を見て理解はできるものの、相変わらず具体的に自分がもし使うなら?というのをぱっと想像できない。

Ruby の private と protected 。歴史と使い分け - Qiita

せめて名前が出てきたときに「え、何?」とならないように覚えておきたい。

Ruby on Rails

最近、RubyCSSにかまかけてRailsを全く触っていないので、まずいと思い前々からやってみようと思っていたRailsチュートリアルに手を出そうと思う。

やんばるエキスパートでは、同じ時期に入会した人たちと週に一回メンターの方も含めてミーティングをするのだが、その際にRailsチュートリアルはどうですか、と尋ねると、意外とそこまで必須でもないという感じの反応だったので、とりあえずあまりにも時間がかかりそうだったらやめておくという方向性で進めたい。

以前AWSに登録しようと思い、何度か試したがうまく登録できなくて途方に暮れていたが、今登録したら出来たのでよかった。

Railsチュートリアル

ディレクトリとファイルの構造

Rails newを実行すると、自動的に必要な諸々のファイルが作成される。

が、今まで「このファイルに○○が入っている」「○○はここ」のような適当な暗記をしていた。

Railsチュートリアルに、ディレクトリとファイルの構造が分かりやすく記載されていた。

MVCモデル

面接で、「MVCモデルを説明してください」と問われることがそこそこあるらしい。

自分の言葉で説明できるように、曖昧にせずしっかり覚えないといけないなと感じた。

Railsチュートリアルでも、最初の段階でMVCモデルの説明が始まる。

MVCモデルは、アーキテクチャパターンの一種。アーキテクチャは、構造・構成という意味なので、平たく言えば構造パターンになる。

MVCモデルの処理の流れを覚えることが、デバッグツールを使う上で非常に重要だったことから、流れを理解しておく必要性を強く感じている。

コントローラ
リクエストを処理する役割がある
モデルとビューを繋ぐ

モデル
データベースとの通信を担当しているRubyのオブジェクト
データベースに関する命令を書く

ビュー
リクエストされた内容をもとに、ユーザーが見るHTMLをブラウザに送り返す

この三つの役割に応じて、何のプログラムをどこに書くか決められている。

役割を三つに分けて、役割ごとにファイルが分かれているので、どこに何を書けばいいのかが分かりやすい。

そのため、プログラムの管理や追加がしやすいというメリットがある。

ルーター(router)は、コントローラとブラウザの間に配置され、ブラウザからのリクエストをコントローラに振り分ける(これがルーティング)。

ルートルーティング

今ではもうすっかりresourcesで簡略化するようになってしまったが、ルートの記述方法をもう一度確認しておく。

root "controllerの名前#actionの名前"

# userコントローラのshowアクションに設定したい場合
root "user#show"
resources :user

# 上のように設定するだけで、標準的なuserアクション
# (index、create・new・edit・show・update・destroy)
# を一括で作成してくれる!便利すぎる

Git

GitHubにpushできない

毎度pushできなくなっているが、Railsチュートリアル中にAWS Cloud9上からpushするぞ、と思ったら、GitHubでのusernameとpasswordを尋ねられる。

合っているはずなのに何度やっても上手くいかず、色々と解決策を探していたところ、こちらの記事の通りにやるとうまくpushすることができた。

Githubで2段階認証を設定しhttpsリポジトリにpushする - hatappi.blog

二段階認証を自分で設定しておきながら、「???」となってしまった。大変助かった。