概要
Replace "string typing" with classes
前提
Confident Rubyではメソッド内の処理を次のように分類しています。
・Collecting Inputs(引数チェック、変換など)
・Performing Work(主処理)
・Delivering Output(戻り値に関わる処理)
・Handling Failure(例外処理)
当記事は上記のうち、Collecting Inputsに関する話です。
詳細
状況
入力データは特定のフォーマットの文字列。
Stringの中身は様々なステートメントの分岐がある。
概要
特別な意味を持つ文字列をユーザー定義の型に置換する。
理由
多態性に傾いた意思決定を行うことが、
オブジェクトの設計を明確にし、不要な冗長性やミスの機会を減らすことができるため。
サンプルコード仕様
RPGの戦士を表したクラスの状態を3つ定義します。
元気=Normal
毒=Poison
呪い=Curse
サンプルコード(ステータスごとに分岐したバージョン)
class Fighter def change_status(status) case status when :normal @status = "元気" when :poison @status = "毒" when :curse @status = "呪い" else fail 'invalid status' end end def show_status "ステータスは#{@status}" end end f = Fighter.new f.change_status(:normal) puts f.show_status f.change_status(:poison) puts f.show_status f.change_status(:curse) puts f.show_status
出力
ステータスは元気 ステータスは毒 ステータスは呪い
サンプルコード(文字列をクラスに変換したバージョン)
class Fighter [ {klass: :Normal, status: "元気"}, {klass: :Poison, status: "毒"}, {klass: :Curse, status: "呪い"}, ].each do |klass_status| const_set(klass_status[:klass], Class.new do |klass| define_method :status do klass_status[:status] end end) end def change_status(status) @status = self.class.const_get(status.to_s.capitalize).new.status end def show_status "ステータスは#{@status}" end end f = Fighter.new f.change_status(:normal) puts f.show_status f.change_status(:poison) puts f.show_status f.change_status(:curse) puts f.show_status
出力
ステータスは元気 ステータスは毒 ステータスは呪い