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

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

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

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

Q&A

解決済

1回答

4043閲覧

教科の平均点を出すアプリケーションをクラスを使って書き換えてみたいです。

退会済みユーザー

退会済みユーザー

総合スコア0

Ruby

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

1グッド

1クリップ

投稿2017/01/04 07:32

現在はインスタンスメソッドを使ったコードを構成しました。
このコードをクラスとインスタンスを使って書き換えたいです。
自分でも考えてみましたが手の付け所がわからず、よりよいコードを知りたいので、みなさんの考えを教えてほしく投稿いたしました。

よろしくお願いいたします。

ruby

1def input_score 2 score = {} 3 puts "教科を入力してね" 4 score[:subject] = gets.chomp 5 puts "得点を入力してね" 6 score[:score] = gets.to_i 7 8 return score 9end 10 11def show_all_score(a_scores) 12 sum = 0 13 line = "-------------------------" 14 puts line 15 16 a_scores = a_scores.sort{|a, b| b[:score] <=> a[:score] } 17 a_scores.each do |score| 18 puts "#{score[:subject]} : #{score[:score]}点" 19 sum = sum + score[:score] 20 end 21 22 puts line 23 puts "平均得点は : #{sum/a_scores.count}点です!" 24end 25 26 27scores = [] 28 29while true do 30 puts "テストの平均点を算出してみよう" 31 puts "得点を入力する! | する[0] しない[1]" 32 input = gets.to_i 33 34 if input == 0 35 scores << input_score 36 elsif input == 1 37 show_all_score(scores) 38 exit 39 end 40end 41
DrqYuto👍を押しています

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

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

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

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

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

guest

回答1

0

ベストアンサー

単純に答えを書いてしまうよりちゃんと理解した方が良いと思ったのでちょっとだけ長くなります。

クラス化する、という意味を把握すると理解しやすくなるかと思います。クラス化するという事はそのクラスが内包するデータと一連の処理が、異なる状態で個別に保持され処理される事を意味します。
このケースであれば、何が個別であるべきかと考えると入力中の成績がそれにあたるかと思います。

この例は画面から入力する形式です。なので入力操作がPCに対して1つしか存在しえない事になります。なおかつこの例は1人の成績を入力するプログラムです。
つまりクラス化の題材としてはあまり良く無いのですが、敢えてこれをクラス化するならば以下の様になるかと思います。

ruby

1def input_score 2 score = {} 3 puts "教科を入力してね" 4 score[:subject] = gets.chomp 5 puts "得点を入力してね" 6 score[:score] = gets.to_i 7 8 return score 9end 10 11 12class Student 13 @@scores = [] 14 15 def show_all_score 16 sum = 0 17 line = "-------------------------" 18 puts line 19 20 @@scores.sort{|a, b| b[:score] <=> a[:score] }.each do |score| 21 puts "#{score[:subject]} : #{score[:score]}点" 22 sum = sum + score[:score] 23 end 24 25 puts line 26 if @@scores.count > 0 27 puts "平均得点は : #{sum/@@scores.size}点です!" 28 end 29 end 30 31 def input 32 puts "テストの平均点を算出してみよう" 33 puts "得点を入力する! | する[0] しない[1]" 34 input = gets.to_i 35 36 if input == 0 37 @@scores << input_score 38 elsif input == 1 39 self.show_all_score 40 break 41 end 42 end 43end 44 45s = Student.new 46while true do 47 s.input 48end

Student は個別に1人の成績を保持するクラスになりました。ここでなぜ input_score をメソッドにしなかったのかを考えてみて下さい。画面とのやりとりは基本同時に1つしか実行しえませんよね。そういった処理をメソッドにしてしまうと必要のない環境依存(画面入力という依存)に縛られます。そうさせない為にはクラスから切り離すといった実装にする事が多いです。(ただし場合によります)
さて、この例は1人の成績を続けて入力するプログラムですが、例えば入力のシーケンスを以下に変更すると考えてみて下さい。

  • 誰が
  • どの教科で
  • 何点だった

そうすると Student の構造は以下の様になると連想できますよね。

ruby

1class Student 2 @@name = '' 3 @@scores = [] 4 def initialize(name) 5 @@name = name 6 end 7end

そして入力操作も input_score に移る前に名前を入力させる形式が良いと連想できますよね。この Student を生徒ID や生徒名をキーにした Hash とし、値として Student を格納すれば、学級内の成績を管理できる事が連想できるかと思います。

ruby

1students = Hash.new 2while true do 3 name = input_name 4 students[name] ||= Student.new(name) 5 students[name].input 6end

これをオリジナルのコードの延長線上で実装するならば scores (配列)を値に持つ Hash にしてしまいがちですが、上記の様にクラスとして保持する事で、今後メソッドを増やす際に扱いやすくなります。
例えば、生徒を合格にしたり失格にするメソッドを簡単に追加できる様になります。

クラス化とはどんなデータや処理の固まりを纏めるかを予め意識しておくと実装しやすくなります。上記で私が書いたコードが正解という訳ではないので、ご自身で理解して「何を保持して」「どう処理したい」を検討して答えを出した方が良いかと思います。

投稿2017/01/04 12:18

編集2017/01/04 12:24
mattn

総合スコア5030

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

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

退会済みユーザー

退会済みユーザー

2017/01/04 14:26

ご回答いただきましてありがとうございます。 Classの中にinput_scoreは環境依存してしまうからNGの場合があるということ、初めて知ることなので大変参考になります。 show_all_scoreでハッシュを引数にして渡していましたが、クラス変数を用いて自己代入演算子で@@scoresをeachで分解していて、こういう方法もあるのかと驚いております。 クラス化するときは、そうするに値する処理の塊があるときに実装するということで、今後はコードを無造作に書き始めるのではなく、あらかじめ設計して書いていきたいとおもいます! ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問