Menu
CoddyTech

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، قبل أداة ضبط القيمة:

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 على مُعيّن مخصّص balance= يثير ArgumentError مع balance cannot be negative عندما تكون القيمة أقل من 0. أكمل initialize(owner, balance) وdeposit(amount) وwithdraw(amount) بحيث يمرّ كل تغيير في الرصيد عبر ذلك المُعيّن باستخدام 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 عبر الإنترنت