Menu
Coddy logo textTech

self במתודות

חלק מהיחידה תכנות מונחה עצמים במסלול ה-Ruby של Coddy. שיעור 9 מתוך 57.

בתוך מתודה, name = value תמיד יוצר משתנה מקומי, גם כאשר למחלקה יש קובע name=. כדי לקרוא לקובע, כתבו את המקבל: self.name = value:

class Player
  attr_accessor :level

  def initialize
    @level = 1
  end

  def broken_level_up
    level = level + 1
  rescue NoMethodError
    puts "level is a new local variable here, still nil"
  end

  def level_up
    self.level = level + 1
  end
end

p1 = Player.new
p1.broken_level_up
p1.level_up
puts p1.level

פלט:

level is a new local variable here, still nil
2

אין צורך לכתוב self.: הקריאות ל־level ול־self.level מפעילות את אותה מתודה. בסגנון המקובל כותבים self. רק במקומות שבהם Ruby דורשת זאת, לפני setter:

class Rect
  attr_accessor :w, :h

  def initialize(w, h)
    @w = w
    @h = h
  end

  def area
    w * h
  end

  def double!
    self.w = w * 2
    self.h = self.h * 2
    self
  end
end

puts Rect.new(2, 3).double!.area

פלט:

24

קריאה למגדיר מתוך initialize עם self. גורמת לכך שאובייקטים חדשים יעברו את אותה בדיקה כמו שינויים מאוחרים יותר, כך שהכלל מוגדר במקום אחד:

class Product
  attr_reader :price

  def initialize(price)
    self.price = price
  end

  def price=(value)
    raise ArgumentError, "price must be positive" if value <= 0

    @price = value
  end
end

puts Product.new(5).price
begin
  Product.new(0)
rescue ArgumentError => e
  puts e.message
end

פלט:

5
price must be positive

מהו self תלוי במקום שבו הקוד רץ. בתוך מתודת מופע הוא המופע; בגוף המחלקה, מחוץ לכל מתודה, הוא המחלקה עצמה:

class Robot
  puts "in the class body, self is #{self}"

  def whoami
    "in a method, self is a #{self.class}"
  end
end

puts Robot.new.whoami

פלט:

in the class body, self is Robot
in a method, self is a Robot
challenge icon

אתגר

קל

למחלקה Account יש setter מותאם אישית balance= שמעלה ArgumentError עם balance cannot be negative עבור ערך הנמוך מ־0. השלימו את initialize(owner, balance), את deposit(amount) ואת withdraw(amount), כך שכל שינוי ביתרה יעבור דרך ה־setter הזה באמצעות self., כולל היתרה ההתחלתית.

הקוד שסופק קורא את שם הבעלים ואת היתרה ההתחלתית, ולאחר מכן פקודות +n (הפקדה) או -n (משיכה). הוא מדפיס Ada: 120 אחרי כל פקודה, או את הודעת השגיאה ואת היתרה שלא השתנתה. יתרה התחלתית לא תקינה מדפיסה את הודעת השגיאה בלבד.

הקוד שלכם ייכתב ב־account.rb. הקובץ main.rb מכיל את קוד הקלט/פלט שסופק ואי אפשר לערוך אותו.

נסו בעצמכם

require_relative 'account'

# קוד הקלט/פלט שסופק: יש להשאיר אותו כפי שהוא
input = []
while (line = gets)
  input << line.chomp
end
begin
  account = Account.new(input[0], input[1].to_i)
  input.drop(2).each do |cmd|
    begin
      amount = cmd[1..].to_i
      cmd.start_with?("+") ? account.deposit(amount) : account.withdraw(amount)
    rescue ArgumentError => e
      puts e.message
    end
    puts "#{account.owner}: #{account.balance}"
  end
rescue ArgumentError => e
  puts e.message
end
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר Ruby אונליין