31日目
今日の学習
Ruby
リファクタリング
昨日取り組んだ課題を、やんばるエキスパートのメンターの方に見ていただき、望ましいリファクタリングを色々と教えていただけたのでメモ。
全体的に、プログラムを動かす段階にたどり着いて安堵してしまい、細かいところまで気が回っていなかった。
完成できた!と思ったあとは、しっかり見直して整えたり、不要なものがないかを探す癖をつけたい。
不必要な改行を避ける
単純に隙間が空いていたら見やすいだろう等と考えていたり、完成させられたことに気を取られて最後に全体を整える作業を行なっていなかった。
フォーマッターに、勝手に揃えてくれる機能がありそうな気はするが、今回は手動で直してみると、確かに謎の改行部分があった。
- 改行は基本的に一行にする
変数に複数のクラスインスタンスを配列として代入
monsters = [ monster1 = Monster.new(name: "モンスター", hp: 300, offense: 180, defense: 100), monster2 = Monster.new(name: "ドラゴン", hp: 350, offense: 200, defense: 150) ] monster = monsters.sample
このように、(2体しか設定していないが)モンスターをランダムで出現させるような形を取っていた。
変数に配列を代入していたのだが、中で割り振っているmonster1
やmonster2
は使用していないので、不要だ。なので、
monsters = [ Monster.new(name: "モンスター", hp: 300, offense: 180, defense: 100), Monster.new(name: "ドラゴン", hp: 350, offense: 200, defense: 150) ] monster = monsters.sample
このように書くことができる。
使わないものをわざわざ書かないようにしたい。
処理の中ではインデントをする
loop処理を使っていたが、その箇所のインデントができていなかった。
インデントされていない処理を改めて見てみると、かなり見にくいと感じた。インデント大事。
ただ、改行もそうなのだが、「適切な改行は?」「ここはどれくらいインデントをすればよいか?」というコーディングの決まりみたいなものを、そもそも知っておくべきなのではと強く感じた。
キレイで読みやすいRubyコードを書くために。RuboCopスタイルガイド レイアウト編 | よこのじ.work
これを機に、もっとRuboCopをうまく活用して、綺麗なコードが書けるようになりたい。
また、最近クイズプログラムのリファクタリングもしていただけたので、追々指摘していただいた部分を直しつつ、形になったらQiitaに制作過程を書いてみようかなと考えている。
クラスの継承
Ruby本で学習。サンプルプログラムといい、一気に内容が難しくなってきた...。
Progateで継承の存在や、簡単な使い方は学んだが、自発的に利用したことはないのでちゃんと考え方を叩き込んでおきたい。
継承元のクラスをスーパークラス
、継承し新しく作成するクラスをサブクラス
と呼ぶ。
これはis-aの関係
というもので、違和感がないかどうかを確かめられる。
スーパークラスがAnimal
で、サブクラスがCat
であれば
、Cat is an animal
と言える。これがis-aの関係
。
initialize
スーパークラス、クラスどちらでも同じ値をinitializeメソッドで代入しているとき、super
を使うとスーパークラスの同盟メソッドを呼び出すことができる。
class Animal def initialize(name) @name = name end end # ↓Catクラスに継承しても、nameを使用したい class Cat < Animal def initialize(name, breed) # スーパークラスのinitializeメソッドを呼び出す super(name) @breed = breed end end
オーバーライド
サブクラスで、スーパークラスと同名のメソッドを定義することで、スーパークラスの処理を上書きできる。
# 先ほどの内容のまま重要な部分だけ記載 class Animal def introduce puts "こんにちは、#{@name}です!" end end class Cat < Animal def introduce puts "こんにちは、#{@name}です! 猫種は#{@breed}です!" end end
これで、introduceメソッドの中身が書き変わっている。
このメソッドは、「こんにちは、#{@name}です!」の部分が共通しているので、以下のようにスーパークラスのメソッドを活用することができる。
class Cat < Animal def introduce puts "#{super} 猫種は#{@breed}です!" end end
メソッドの公開レベル
メソッドには、三つの公開レベルがある。
- public
- protected
- private
initializeメソッド以外のインスタンスメソッドは、デフォルトでpublic
メソッドになるため、自分がこれまでに何気なく使っていたメソッドの大半はpublic
メソッドということになる。
private
メソッドに関しては、Railsでコントローラの一番下に書いたりはしているが、なぜprivate
メソッドでなくてはならないのか?ということを深く考えていなかった。
クラス内でprivate
と記述をすると、その位置から下に書かれたメソッドはprivate
メソッドになる。
private
メソッドは、クラスの内部だけで使用できるメソッドで、外部から呼び出すことはできない。
レシーバを指定して呼び出すことができないメソッド
ということらしい。
レシーバ
とは、「メソッドを呼び出された側」という意味を持つ表現。
先ほどのコードを使ったcat.introduce
というコードでは、「introduceメソッドのレシーバはcat」ということになる。
ただ、定義したクラス内だけではなく、サブクラス内でも呼び出すことができる。
そのため、スーパークラスのprivateメソッドをオーバーライドしてしまった!ということもあるので、サブクラスでメソッドを作成する場合はスーパークラスのメソッドもしっかり確認しておく。