学習記録 2日目
今日も頑張っていきます。昨日は勉強したあとにブログにまとめましたが、学習と平行してブログ記事へアウトプットを行った方が頭に入るので今日からはそうしていきます。
学習内容
正規表現
昨日に引き続き以下のサイトを使って正規表現の練習をしました。
http://www2.otani.ac.jp/fkdsemi/seikihyogen/mondai.html
解答と回答が異なった問題を記録しておきます。
- 3-2. 時刻を求める
/([01][0-9]|2[0123]):([0-5][0-9])/ #解答 /([01]\d|2[0-3]):[0-5]\d/ #回答
[0-9]を\dで回答。同義のためOK
- 3-3. 日付への一致 2
/(200[0-9])年([1-9]|1[0-2])月([1-9]|[12][0-9]|3[01])日/ #解答 /200\d年1?\d月[1-3]?\d日/ #回答
回答だと19月36日等の実在しない文も拾ってしまう。
- 3-4. 日付への一致 3
/(19[0-9][0-9]|200[0-9])年([1-9]|1[0-2])月([1-9]|[12][0-9]|3[01])日/ #解答 /(19\d{2}|200\d)年(1[0-2]|\d)月([12]?\d|3[01])日/ #回答
解答は日の取得が冗長な気がします。
- 3-6. カタカナ語の伸ばし棒への一致
/[ァ-ヶー]+ー/ #解答 /[ア-ンー]+ー/ #回答
カタカナの抽出は[ァ-ヶ]らしいので覚えます。他にもひらがなは[ぁ-ん], 半角カタカナは[ヲ-゚]らしい。半角カタカナの-゚はどうやって打つんだ…以下参考文献。
https://qiita.com/kokorinosoba/items/78811d7e2b6bc424b1b1
- 3-8. ドル表記への一致
/\$[0-9]+(\.[0-9][0-9])?/ #解答 /\$\d+\.?\d{0,2}/ #回答
回答では1.0等小数点以下第一位の表記でも対応しようと思い\d{0,2}にした。
- 3-10. ディレクトリパスへの一致
/.*// #解答 /.+\// #回答
/はエスケープ必要。ディレクトリパスはあることが前提なので*ではなく+の方がいい気がします。
- 3-11. ファイル名への一致
/^.*// #解答 /(?!.+\/).+/ #回答
否定の^でよかったですね。
プロを目指す人のためのRuby入門 8章
モジュールについて学んでいきます。C#にはおそらくなかった機能なので(イントロダクション読んだ感じstatic classっぽい?)学習が楽しみです。
気になったところや忘れそうなところをまとめていきます。
- モジュールをミックスインするにはincludeまたはextendを使用する。includeはインスタンスメソッド, extendはクラスメソッドとして呼び出す。インスタンスメソッドはオブジェクトから読み込めるメソッド。クラスメソッドは例えばUser.method()と呼び出せるがオブジェクトからは呼び出せない。
- is_a?メソッドは引数がスーパークラスだけでなくincludeされたモジュールの場合真を返す。
- モジュールメソッド内でself.を使用するとinclude先のクラスのインスタンスになる
- Enumberableモジュールはeachメソッドを定義すれば自作クラスにincludeできmap, select, find, countメソッド等が使用出来るようになる。
- <=>演算子は差を返すわけではない。1, 0, -1, nilを返す。
- Kernelモジュールはメソッドのどこからでも使用可能。Objectクラス内でincludeしているため。
Object.include?(Kernel) #=> true
- クラス構文の外やirb起動時のmainはトップレベルにいるオブジェクトの名称。Javaのpublic static void main(string args[]){ };みたいな感じかな?
- RubyではClassクラスもModuleクラスもObjectクラスを継承している。何もかもがオブジェクトなのは面白い。
class User end User.class #=> Class Class.superclass #=> Module module Loggable end Loggable.class #=> Module Module.superclass #=> Object
- モジュール内でインスタンス変数を読み書きする場合はゲッター, セッターを経由させる。
module NameChanger def change_name #include先のクラスのインスタンス変数を変える @name = 'ありす' # この場合include先に@nameが無くても動いてしまう self.name = 'ありす' # セッター経由でデータを変更すれば@nameが無い場合エラーになる end end
- 大規模なプログラムやライブラリを作成する際はモジュール内にクラスを書きクラス名の衝突を防ぐ。クラスへアクセスするにはModule::Classと記述する。
- モジュール内にクラスを記載する場合ネストさせずに記載が可能。本書の例で出しているAliasTrackerクラスはネストさせているため必ずしもネストが深いことが悪いことではなさそう?
module Baseball end class Baseball::Second #省略 end
- インスタンス化させる必要のないクラスはモジュールで書いた方が他の読み手に変な勘違いをさせずに済む。
- クラスを使用してシングルトンパターンを実現するにはSingletonモジュールをincludeさせる。newメソッドが使用できなくなりincludeメソッドでオブジェクトを作成する。オブジェクトで変更したインスタンス変数は他のオブジェクトでも変更されている。(object_idが同じになる)
- prependメソッドでモジュールをミックスインした場合、同名メソッドがあってもモジュール内のメソッドが優先して呼び出される。
- refinementsを使用することでライブラリのオーバーライドの適応範囲を限定することが出来る。
- refineはRuby2.4からクラスだけでなくモジュールも可能になった。
- ::と.の違いは右側にメソッド以外のものが記載出来るか
Module::Class.method #=> PASS Module::Class.CONST #=> ERROR Module::Class::method #=> PASS Module::Class::CONST #=> PASS
モジュールには以下の使い方があることを学びました。
- 共通のメソッドをライブラリのようにして使用する。
- クラス同士の名前の衝突を避けるためにモジュール内にクラスを定義する。
- モジュールに特異メソッドや定数を定義してモジュール単体で使用する。(Rubyの組込みライブラリでいうMathモジュール)
- ライブラリ内で使用する設定値をモジュールに保持させる。(=シングルトンパターン)
リーダブルコード 7章
- 条件式の引数の並びは 調査対象, 比較対象が好ましい。
if length < 10 #省略 end
- 条件式は否定形よりも肯定形を使用する。Rubyではunlessがある。ただしunlessはelsifがない。
- 条件式の順番は単純な条件から書く。
- 単純な条件式の場合、三項演算子を使用した方が読みやすくなる。
# 冗長なコード if hour >= 12 time_str += 'pm' else time_str += 'am' end # 三項演算子を使用することで1行の簡潔なコードに time_str += hour >= 12 ? 'pm' : 'am'
- ネストを浅くする。私が今までゲーム制作で書いていたコードはif文だらけで地獄のようなコードだった。早期リターン等を使ってネストは浅くする。
# ネストが深く理解しづらい if user_result == SUCCESS if permission_result != SUCCESS reply.WriteErrors('error') return end reply.WriteErrors('') else reply.WriteErrors(user_result) end reply.Done # 上記のコードを整理するとネストを削除出来る unless user_result == SUCCESS reply.WrriteErrors(user_result) reply.Done return end unless permission_result == SUCCESS reply.WrriteErrors('error') reply.Done return end reply.WrriteErrors('') reply.Done
本日の総括
- モジュールについて理解出来た。オブジェクト指向について深く学びたくなってきたので時間があれば本書で勧めていた「オブジェクト指向設計実践ガイド Rubyでわかる進化しつづける柔軟なアプリケーションの育て方」を読んでみたいと思う。
- リーダブルコード 7章は内容の半分ほどは理解出来た。全体を通してまだ理解出来ない箇所があるのでもう少しレベルが上がったら再度読み直したい。