(4)10/19の授業内容

  1. メソッドとは
  2. これまで使用してきたprint、gets、to_iなどは、決められた手順を実行し、その結果を返してくれるものでした。このような働きをするものをメソッドと呼んできました。

    メソッドは自分で作ることもできます。今日は、自分でメソッドを作る方法について学びます。

  3. メソッドの定義方法
  4. メソッドを定義するにはdefを利用します。

    def メソッド名(引数リスト)
      定義本体
    end

    簡単なメソッドを定義した例を見てみましょう

    消費税を計算するメソッド:shohizei(shohizei.rb)

    #!/usr/koeki/bin/ruby
    
    def shohizei(a)
      a * 1.05
    end
    
    STDERR.print "金額を入力してください"
    item = gets.chomp!.to_i
    printf ("税込み金額は%d円です\n", shohizei(item))

    上記について順を追って説明します。

    消費税を計算するメソッド:tax(tax.rb)

    #!/usr/koeki/bin/ruby
    
    def tax(x)
      price = x * 1.05
      printf ("税込み価格は%d円です\n",price)
    end
    
    STDERR.print "金額を入力してください"
    item = gets.chomp!.to_i
    tax(item)

    突然新しい表現方法が出てくると戸惑うかもしれません。でも、実際は下記のプログラムを書き直しただけなのです。

    #!/usr/koeki/bin/ruby
    
    STDERR.print "金額を入力してください"
    item = gets.chomp!.to_i
      price = item * 1.05
      printf ("税込み価格は%d円です\n",price)

    なぜこんな手間のかかる作業が必要なのでしょうか。あえてメソッドを定義しなくても、そのまま素直に書けばいいのにと思うかもしれません。確かにこのような単純で短いプログラムではdef-endを使う意味はあまりありません。

    では、1000行程度の長いプログラムを書くことを考えてみましょう。長いプログラムを書く際には、同一の処理が複数の場所で出てくることがあります。また、できる限りすっきりと書いて、全体の流れをわかりやすくしたいとも思います。def-endを使うことで、複数箇所における同一処理は1つにまとめることができます。これによりプログラムを短く書くことができます。また、インターネットの掲示板を作ることを考えてみましょう。掲示板の主要な働きは投稿されたコメントを表示するというものです。しかし、これ以外にも細かな処理として(1)記述されたURLに自動的にリンクを貼る、(2)画像付き掲示板の場合画像のサイズを調べ、大きすぎる場合はエラー表示を出す、(3)コメントを投稿者が削除しようとした時に入力時のパスワードと、削除処理時のパスワードを照合する、等があります。これらも全てプログラムの中に書いていくわけですが、そのまま書くととてつもなく長いプログラムになり、プログラムの全体像を把握するのが難しくなります。URLkinkメソッドを定義して、プログラム本体にはURLlinkとだけ明記しておき、実際にURLの自動リンクを行う処理はdef-endの中で定義しておけば、プログラム本体はすっきりし、流れがわかりやすくなります。

  5. def-end利用上の注意
  6. 呼び出す前に定義をする

    def-endで定義をしたメソッドを呼び出す場合、呼び出す前に定義が行われている必要があります。定義が下に書かれていても呼び出せません

    引数は1つとは限らない

    shohizeiやtaxは引数が1つしかありませんでしたが、0の場合や2つ以上の場合もあります。

    引数が0の場合(単にこんにちはと表示するだけのメソッド:hello)

    #!/usr/koeki/bin/ruby
    
    def hello()
      print "こんにちは!\n"
    end
    
    hello

    引数が不要な場合は、引数リストのカッコ内は空にします。

    引数が2の場合(三角形の面積を求めるメソッド:triangle)

    #!/usr/koeki/bin/ruby
    
    def triangle(x,y)
      menseki = x * y / 2
      printf ("面積は%4.2f平方センチメートルです\n",menseki)
    end
    
    STDERR.print "底辺をcm単位で入力してください"
    teihen = gets.chomp!.to_f
    STDERR.print "高さをcm単位で入力してください"
    takasa = gets.chomp!.to_f
    triangle(teihen, takasa)

    引数が2の場合(三角形の面積を求めるメソッド:sankaku)

    #!/usr/koeki/bin/ruby
    
    def sankaku(x,y)
      x * y / 2
    end
    
    STDERR.print "底辺をcm単位で入力してください"
    teihen = gets.chomp!.to_f
    STDERR.print "高さをcm単位で入力してください"
    takasa = gets.chomp!.to_f
    printf ("面積は%4.2f平方センチメートルです\n",sankaku(teihen, takasa))

    メソッドの返り値は最後の行の結果とは限らない

    if-endを使った場合には最後の行の結果が返り値とはならないことがあります。

    #!/usr/koeki/bin/ruby
    
    def min(x,y)
      if x < y
        (return) x  #returnは省略可能
      else
        (return) y  #returnは省略可能
      end
    end
    

    def-end部分のみですが、これは2つの引数を比較して小さい方を返り値とするというメソッド(min)です。最後の行ではなく、途中で値を返す場合にはreturnを使いますが省略可能です。

    引数にはデフォルト値を指定することができる

    引数が必要なメソッドにおいて、引数が省略された場合に適用される値(デフォルト値)を指定しておくことができます

    #!/usr/koeki/bin/ruby
    
    def sankaku(x,y=10)
      x * y / 2
    end
    
    printf ("面積は%4.2f平方センチメートルです\n", sankaku(5))  #=>5*10/2=25
    printf ("面積は%4.2f平方センチメートルです\n", sankaku(5,8))  #=>5*8/2=20

    上記の例ではyのデフォルト値として10が与えられている。sankaku(5)で呼び出した場合は、xの値しか指定していないのでyには自動的に10が代入される。sankaku(5,8)で呼び出した場合はx、yいずれも値が指定されているのでデフォルト値は代入されない。

    なお、定義したメソッドを呼ぶときは引数を順番に与えていくため、前の引数を省略して後ろの引数を指定することはできません。具体的に言うと、上記の例でsankaku(5)となっている場合、5は自動的にxに与えられます。このため、xにデフォルト値を与え、yには与えていない場合はエラーになってしまいます。したがって、

    ○ def sankaku(x=10, y=8) 
    ○ def sankaku(x, y=8) 
    × def sankaku(x=10, y) 

    となります。

    メソッドに配列を渡すこともできる

    2回目の授業のbokin.rbを改良してみましょう。募金の合計額を算出するtotalというメソッドを定義します。

    #!/usr/koeki/bin/ruby
    
    def total(yen)  #yenは数値の入っている配列
      sum = 0
      x = 0
      while x < yen.length-1  #.lengthで配列の中のデータの個数を調べる
        sum += yen[x]
        x += 1
      end
      sum  #最終行が返り値となるので単にsumと書いている
    end
    
    bokin = []
    i = 0
    
    while true
      STDERR.print "募金お願いします"
      bokin[i] = gets.chomp!.to_i
    
      if bokin[i] == 0
        then break
      end
    
      i += 1
    end
    
    printf ("募金の合計は%d円でした\n",total(bokin))

本日の課題

引数を2つ以上必要とするメソッドをdef-endを用いて定義し、それを利用するプログラム書いてください。面白いものや日常生活で役に立ちそうなものを題材とするとよい


作成したプログラムや実行結果をメールでnaoya@e.koeki-u.ac.jp宛に送る

課題の提出期限は10月25日(火)23:59までです


メール送信時の注意

説明のポイント:今回は人によって全く内容が異なるプログラムが出来上がるはずです。何をするプログラムなのか、定義したメソッドが行う処理は何かについて説明しているかどうかを中心に評価します。

レポート採点基準:期限内提出(2点)、プログラムの正誤(3点)、説明(2点)、役立ち度や面白さ、オリジナリティ(2点)、指示通りにメールを送っているか(1点)

Tips

emacsについて

Mewについて