質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

Q&A

解決済

4回答

540閲覧

条件分岐を無くしたい

oeiqgfodgfhps

総合スコア35

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

if

if文とは様々なプログラミング言語で使用される制御構文の一種であり、条件によって処理の流れを制御します。

0グッド

0クリップ

投稿2021/11/30 14:23

rubyを使ってあるプログラムを書いています。
ユーザーから入力を受け取り、その入力された値によって、出力を変えるプログラムを書こうとしているのですが、switch文で条件分岐しており、今後条件が増えたときにコードが増えそうで、嫌な感じがします。
各条件分岐で使用するクラスは性質としては似たものなので、共通の親クラスを持たせています。
何かこの共通するクラスをうまく使って、条件分岐を消す方法はないでしょうか??
ポリモーフィズムを活用し、オブジェクトに振る舞いを持たせる方法も考えたのですが、どのオブジェクトを使用するかによって、結局条件分岐が必要なので、難しいです。

case input when "A" then # Aについての処理 when "B" then # Bについての処理 when "C" then # Cについての処理 end class Parent end class A < Parent end class B < Parent end class C < Parent end

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

他の回答にあるように、表引きで条件分岐を置き換えるのが一般的だと思います。
この回答では、各クラス(またはベースクラス) に条件判定を持たせるという方法で書いてみました。

pr.rb

ruby

1class BaseCommand 2 def check(commnd) = commnd == self.class.name 3 def run() = raise('Abstract Class !!') 4end 5 6class A < BaseCommand 7 def run 8 puts 'run by A.' 9 end 10end 11 12class B < BaseCommand 13 def run 14 puts 'run by B.' 15 end 16end 17 18class C < BaseCommand 19 def run 20 puts 'run by C.' 21 end 22end 23 24def execute(command) 25 ACTORS.each do |cls| 26 return cls.run if cls.check(command) 27 end 28 puts ' --- ignore the command.' 29end 30 31# ---- Main ------ 32ACTORS = [A.new, B.new, C.new].freeze 33 34loop do 35 print('input command:') 36 x = gets 37 break if x.nil? 38 39 execute(x.chomp) 40end 41

実行例
イメージ説明

Ctrl-D の入力で終了します。(Ctrl-C で強制終了しても良いですけど)

投稿2021/12/04 14:43

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

「についての処理」
はみな同じmethod名 にします。 仮に run

で、Parent では

def run raise 適当なError end

しておきます。
calss A,B,C ではしかるべく定義する。
で、ホワイトリストを作るのが嫌なら
eval(input).run
しかし、Parentを入力したときの問題は回避できますが
Dを入れたときに頓挫。
すると ABCのいずれであるか、を判断することになるので
結局ホワイトリストが必要になる、か eval(input).run に対する例外対策を行う。

なんてより otn さんの FOO={"A"=>A, "B"=>B, "C"=>C} でしょうね。
これに default で Parent を入れておけば、ABC以外はParentになって、raise 適当なError になります。
質問の case文ではABC以外は何もしないでよいようなので、でしたらParentのdef run は空にしておく。

投稿2021/12/01 04:17

winterboum

総合スコア23567

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Class.const_get でクラスオブジェクトを取得してインスタンスメソッド(or クラスメソッド)を実行するなど。

ruby

1class Parent 2 def greeting() 3 "I'm a abstract method." 4 end 5end 6 7class A < Parent 8 def greeting() 9 "Hi, I'm #{self.class.name}, now #{Time.now}." 10 end 11end 12 13class B < Parent 14 def greeting() 15 "Hi, I'm #{self.class.name}, rolling dice and got #{rand(1..6)}." 16 end 17end 18 19class C < Parent 20 def greeting() 21 "Hi, I'm #{self.class.name}, 1 + 1 = #{1 + 1} // Q.E.D." 22 end 23end 24 25class D 26end 27 28# testing 29["A", "B", "C", "D", "Parent", "String", "", 1, true, nil].each{|input| 30 output = ((Class.const_get(input) < Parent rescue false) || nil) && 31 Class.const_get(input).new.greeting 32 printf("%8p: %p\n", input, output) 33} 34 35# 36 "A": "Hi, I'm A, now 2021-12-01 03:21:21 +0900." 37 "B": "Hi, I'm B, rolling dice and got 2." 38 "C": "Hi, I'm C, 1 + 1 = 2 // Q.E.D." 39 "D": nil 40"Parent": nil 41"String": nil 42 "": nil 43 1: nil 44 true: nil 45 nil: nil

投稿2021/11/30 16:18

編集2021/11/30 18:23
melian

総合スコア20655

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otn

2021/11/30 16:34

"Parent"という入力をエラーにしないといけないと思いますが。 また、"String"等の入力だとNoMethodErrorですね。 結局、ホワイトリストを持たないと複雑になるだけではないでしょうか。
guest

0

具体的なことが書かれてないので、いまいちやりたいことが不明ですが、
文字列を起因として処理を分ける場合に、明示的に分岐しないのなら表を引くくらいでしょうか。
あるいはevalっぽいことをするか。

投稿2021/11/30 14:42

otn

総合スコア85901

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

oeiqgfodgfhps

2021/11/30 14:46

表を引くとは何でしょうか??
otn

2021/11/30 15:02

A B Cというクラスが定義されていたとして、 FOO={"A"=>A, "B"=>B, "C"=>C} if FOO[input] x = FOO[input].new else ~~ end みたいな。分岐を書く代わりに表を書く必要がありますが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問