عصّارة Johannes

عصّارة Johannes

تمرين تعلّمي

مقدمة

الأصناف مفهوم محوري في البرمجة كائنية التوجه. في Crystal، كل شيء كائن، ولكل كائن نوع، ويمكنه الاستجابة لبعض الطرق. الأصناف مخططات لإنشاء الكائنات، توفر قيمًا ابتدائية للحالة، مثل المتغيرات، وتنفيذات للسلوك، مثل الطرق. الكائنات هي نسخ من الأصناف تحمل جميع متغيرات المثيل والحالات.

تعريف الصنف

يُعرَّف الصنف باستخدام الكلمة المفتاحية class، متبوعة باسم الصنف مكتوبًا بنمط UpperCamelCase.

class Account
end

إنشاء نسخة

لإنشاء نسخة من صنف ما، نادِ اسم الصنف باستخدام الطريقة new.

class Account
end

account = Account.new

في المثال أعلاه، المتغير account هو نسخة من الصنف Account.

عند إنشاء نسخة، تعمل طريقة خاصة تُسمى initialize عمل دالة البناء. وتُستدعى عند إنشاء النسخة. تتيح لك دالة البناء ضبط الحالة الابتدائية للنسخة. يمكن لطريقة initialize أن تستقبل وسائط، تُمرَّر عند إنشاء النسخة.

class Account
  def initialize(number)
    5 + number # => 9
  end
end

Account.new(4)
Note

لا يمكن لطريقة initialize أن تُرجع قيمة يدويًا، بل تُرجع new النسخة المنشأة حديثًا.

class Account
  def initialize(number)
    5 + number
  end
end

Account.new(4)
# => #<Account:0x7f5dc33dcea0>

طرق المثيل

طريقة المثيل هي طريقة متاحة لنسخة من صنف ما، ويمكن استدعاؤها على تلك النسخة. تُعرَّف طرق المثيل باستخدام الكلمة المفتاحية def، متبوعة باسم الطريقة. وتُعرَّف داخل تعريف الصنف.

class Account
  def balance
    100
  end
end

account = Account.new
account.balance # => 100

متغيرات المثيل

متغيرات المثيل هي متغيرات متاحة في جميع طرق النسخة. للوصول إلى متغير مثيل، تحتاج إلى تعريف طريقة مثيل. يمكن تهيئتها في طريقة initialize. وتُعرَّف باستخدام البادئة @.

class Account
  def initialize
    @balance = 100
  end

  def balance
    @balance
  end
end

account = Account.new
account.balance
# => 100

يمكن أيضًا تعريف متغيرات المثيل داخل تعريف الصنف.

class Account
  @age = 0
end

متغيرات المثيل مع التهيئة

يمكن تهيئة متغيرات المثيل بوسيط يُمرَّر إلى طريقة initialize. لأن Crystal لا يستطيع استنتاج نوع الوسيط المستخدم أثناء التهيئة، يجب تحديده. إذا أردت قراءة المزيد عن هذا، يمكنك الاطلاع على: استنتاج النوع. لتحديد نوع المتغير، يمكنك استخدام الرمز :، متبوعًا بالنوع. على سبيل المثال، إذا أردت إنشاء متغير مثيل اسمه balance من النوع Int32، يمكنك فعل ما يلي: @balance : Int32. أو إذا أردت إنشاء متغير مثيل اسمه raining من النوع Bool، يمكنك فعل ما يلي: @raining : Bool.

هناك عدة أساليب لتنفيذ ذلك، إما بتعريف الوسيط بنوعه في طريقة initialize، ثم إسناد متغير المثيل إلى الوسيط، كما في المثال التالي:

class Account
  def initialize(balance : Int32)
    @balance = balance
  end

  def balance
    @balance
  end
end

account = Account.new(1)
account_2 = Account.new(5)

account.balance
# => 1

account_2.balance
# => 5

أسلوب آخر هو تعريف نوع متغير المثيل في تعريف الصنف بالصيغة: @<variable> : <Type>، كما في المثال التالي:

class Weather

  @raining : Bool

  def initialize(raining)
    @raining = raining
  end

  def raining
    @raining
  end
end

weather = Weather.new(true)
weather.raining
# => true

تعديل متغيرات المثيل

يمكن للطرق تعديل متغيرات المثيل. ويمكن استدعاء هذه الطرق على نسخة الصنف. عندما تعدّل طريقة متغير مثيل، فإن هذا التغيير متاح فقط في نسخة الصنف التي استدعيتها عليها.

class Account
  def initialize(balance : Int32)
    @balance = balance
  end

  def withdraw(amount)
    @balance -= amount
  end

  def balance
    @balance
  end
end

account = Account.new(10)
account_2 = Account.new(10)
account.balance
# => 10

account_2.balance
# => 10

account.withdraw(5)
account.balance
# => 5

account_2.balance
# => 10

طرق الصنف

طرق الصنف هي طرق تُعرَّف لصنف ما وليس لنسخه. وهي توفر أسلوبًا لإنشاء طرق لا تعتمد على حالة النسخة. تُعرَّف باستخدام الكلمة المفتاحية def، متبوعة بـ self.<method name>. self إشارة إلى النطاق الذي يُستدعى منه self. في هذه الحالة، يشير إلى الصنف Account. سيكون الأمر مماثلًا لو كتبت Account.، لكن self. هو الأسلوب المفضل.

class Account
  def self.balance
    100
  end
end

Account.balance
# => 100

التعليمات

صديقك Johannes يحب صناعة العتاد بنفسه (اصنعها بنفسك). لقد بنى للتو آلة لتحضير العصير، وJohannes متحمس لها جدًا. هدف Johannes أن يتمكن من تحضير عصير طازج كل صباح.

آلة تحضير العصير فيها الكثير من الميزات الرائعة. مثل نظام قياس مدمج يخبرك بكمية العصير في الكوب. وفيها أيضًا مؤقت يخبرك بالمدة التي عملت فيها الآلة.

Johannes ليس الأفضل في البرمجة، لكنه يريد كتابة برنامج يتحكم بالآلة. ولذلك طلب منك مساعدته.

1. ضوء Debug

في الآلة ضوء Debug، وهو ميكانيزم بسيط: إذا كانت الآلة موصولة بالكهرباء، يكون ضوء Debug مضاءً. ولن يعمل البرنامج إلا إذا كان ضوء Debug مضاءً.

يجب أن تكون هذه الطريقة طريقة صنف باسم JuiceMaker.

عرّف طريقة الصنف JuiceMaker.debug_light_on? التي تُرجع true.

JuiceMaker.debug_light_on?
#=> true

2. تهيئة الآلة

عند تشغيل الآلة، ينبغي أن تُنشئ نسخة من صنف باسم JuiceMaker. ومن المفترض أن تكون للآلة حالة مُهيَّأة. ينبغي أن تحمل الحالة المُهيَّأة المعلومات التالية:

  1. ما إذا كانت الآلة تعمل أم لا. يجب أن تكون هذه دائمًا false عند تشغيل الآلة.
  2. كمية العصير في الكوب، وسيكون هذا مستشعرًا يقيس كمية العصير في الكوب.

عرّف الحالة المُهيَّأة، التي تأخذ كمية العصير في الكوب كمعامل، وأنشئ الحالة المُهيَّأة. ينبغي أن تحتوي الحالة المُهيَّأة على متغير نسخة @running مضبوط على false، ومتغير نسخة @fluid مبني على وسيط يُعطى عند تهيئة الصنف.

JuiceMaker.new(5)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=5>

3. تشغيل الآلة

يمكن تشغيل الآلة وإيقافها. تحتاج إلى تعريف طريقة لتشغيل الآلة. عند تشغيل الآلة، ينبغي ضبط حالة التشغيل على true.

عرّف الطريقة JuiceMaker#start التي تشغّل الآلة.

juice_maker = JuiceMaker.new(5)
juice_maker.start

juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=true, @fluid=5>

4. حالة الآلة

تحتاج الآلة إلى أن تكون قادرة على إخبارك بحالتها. ينبغي أن تُرجع true إذا كانت الآلة تعمل، وfalse إذا لم تكن تعمل.

عرّف الطريقة JuiceMaker#running? التي تُرجع حالة الآلة.

juice_maker = JuiceMaker.new(5)
juice_maker.start

juice_maker.running?
#=> true

5. إضافة العصير

يمكن للآلة أن تضيف عصيرًا إلى الكوب. ويمكن للآلة أن تعرف كمية العصير المُضافة إلى الكوب. تحتاج الآلة إلى مساعدة لمعرفة كمية العصير في الكوب بعد إضافة العصير.

عرّف الطريقة JuiceMaker#add_fluid، التي تأخذ كمية العصير المُضافة كمعامل وتحدّث كمية العصير في الكوب.

juice_maker = JuiceMaker.new(5)
juice_maker.add_fluid(5)

juice_maker
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=10>

6. إيقاف الآلة

يمكن تشغيل الآلة وإيقافها. تحتاج إلى تعريف طريقة لإيقاف الآلة. لن تُستدعى هذه الطريقة إلا عندما تكون الآلة قيد التشغيل. عند إيقاف الآلة، ينبغي ضبط حالة التشغيل على false. وتحتاج الآلة أيضًا إلى مساعدة في تحديد كمية العصير في الكوب بعد إيقافها. تستهلك الآلة خمس وحدات من العصير في الدقيقة.

عرّف الطريقة JuiceMaker#stop التي تأخذ عدد الدقائق التي عملت فيها الآلة كمعامل وتُرجع كمية العصير في الكوب بعد إيقاف الآلة.

juice_maker = JuiceMaker.new(5)

juice_maker.start
juice_maker
#=> <JuiceMaker:0x10f0b8 @running=true, @fluid=5>

juice_maker.stop(1)
#=> #<JuiceMaker:0x10f0b8 @running=false, @fluid=0>
تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة
Crystal Exercism

مستعد لبدء عصّارة Johannes؟

سجّل في Exercism لتتعلّم وتتقن Crystal عبر 26 مفهومًا142 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.