Menu
Coddy logo textTech

メソッドとself

CoddyのRubyジャーニー「オブジェクト指向プログラミング」セクションの一部。レッスン 4/57。

メソッドは、レシーバーを記述せずに同じオブジェクトの別のメソッドを呼び出せます。Rubyはその呼び出しを現在のオブジェクトに送るため、メソッドを組み合わせて処理を構築できます。

class Order
  def initialize(price, quantity)
    @price = price
    @quantity = quantity
  end

  def subtotal
    @price * @quantity
  end

  def shipping
    subtotal >= 50 ? 0 : 5
  end

  def total
    subtotal + shipping
  end
end

puts Order.new(10, 3).total
puts Order.new(20, 3).total

出力:

35
60

メソッド内では、selfはそのメソッドが呼び出された対象のオブジェクトです。selfを返すメソッドを使うと、呼び出し元は同じオブジェクトに対して複数の呼び出しをチェーンできます。

class Counter
  def initialize
    @count = 0
  end

  def add(n)
    @count += n
    self
  end

  def count
    @count
  end
end

puts Counter.new.add(2).add(5).count

出力:

7

オブジェクトは self を使って自分自身を別のコードに渡すこともできます。たとえば、同じクラスの別のオブジェクトとの比較で勝者を返す場合です。

class Player
  def initialize(name, score)
    @name = name
    @score = score
  end

  def name
    @name
  end

  def score
    @score
  end

  def winner_against(other)
    score >= other.score ? self : other
  end
end

ada = Player.new("Ada", 9)
bo = Player.new("Bo", 7)
puts ada.winner_against(bo).name
puts bo.winner_against(ada).name

出力:

Ada
Ada

yes または no の質問に答えるメソッド名は、empty? のように ? で終わります。パラメータにはデフォルト値を設定でき、呼び出し側が引数を省略した場合に使用されます。

class Kettle
  def initialize
    @temp = 20
  end

  def hot?
    @temp >= 90
  end

  def heat(degrees = 10)
    @temp = [@temp + degrees, 100].min
  end
end

k = Kettle.new
k.heat
puts k.hot?
k.heat(75)
puts k.hot?

出力:

false
true
challenge icon

チャレンジ

簡単

ShoppingCart クラスを完成させてください。add(name, price) は商品を保存し、カート自体を返すため、呼び出しをチェーンできます。total は価格の合計を返し、free_shipping? は合計が20以上の場合に true を返し、summary は小数点以下2桁で 3 items, total 12.50(または 1 item, total 4.00)を返します。

提供されたコードは、呼び出しをチェーンして入力行ごとに1つの商品(name price)を追加し、その後 summary と free shipping: true または free shipping: false を出力します。

コードは shopping_cart.rb に記述してください。main.rb には提供された入出力コードが含まれており、編集できません。

自分で試してみよう

require_relative 'shopping_cart'

# 提供された入出力コード: そのままにしておく
input = []
while (line = gets)
  input << line.chomp
end
cart = input.reduce(ShoppingCart.new) do |c, line|
  name, price = line.split
  c.add(name, price.to_f)
end
puts cart.summary
puts "free shipping: #{cart.free_shipping?}"
quiz icon腕試し

このレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。

オブジェクト指向プログラミングのすべてのレッスン

自分で練習してみよう: Rubyオンラインコンパイラ