منطق التحقق من الصحة
جزء من قسم Object Oriented Programming في رحلة Lua على Coddy — الدرس 47 من 70.
حتى الآن، استكشفنا طرقًا مختلفة لحماية البيانات—اصطلاحات التسمية تشير إلى الغرض، والإغلاقات (closures) تخفي المتغيرات تمامًا، والجداول المخصصة للقراءة فقط تمنع جميع التعديلات. ولكن غالبًا ما تحتاج إلى شيء بينهما: السماح بالتغييرات، ولكن فقط التغييرات الصحيحة منها.
هنا تكمن قوة دوال التعيين (setter methods). فبدلاً من مجرد تعيين قيمة، يمكن لدالة التعيين التحقق مما إذا كانت القيمة الجديدة منطقية قبل قبولها:
local Person = {}
Person.__index = Person
function Person:new(name, age)
local obj = {
_name = name,
_age = age
}
setmetatable(obj, Person)
return obj
end
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
endعندما يستدعي شخص ما person:setAge(-5)، تلتقط الطريقة المدخلات غير الصالحة وترفض التحديث. تظل حالة الكائن متسقة. بدون هذه الحماية، يمكن للبيانات الخاطئة أن تفسد برنامجك بصمت—تخيل حساب مزايا التقاعد بعمر سالب.
يمكن أن يكون التحقق من الصحة بسيطاً أو معقداً حسب الحاجة. قد تتحقق من النطاقات، أو تتأكد من الأنواع، أو تضمن مطابقة القيم للتنسيقات المتوقعة. المبدأ الأساسي هو أن دالة التعيين (setter) تعمل كحارس بوابة، مما يضمن دخول البيانات المنطقية فقط إلى الكائن الخاص بك.
التحدي
سهللنقم ببناء فئة Player تحمي سمات الصحة والمستوى باستخدام منطق التحقق في دوال التعيين (setter methods)! يضمن ذلك عدم حصول شخصيات اللعبة أبداً على إحصائيات مستحيلة.
ستقوم بتنظيم الكود الخاص بك عبر ملفين:
Player.lua: قم بإنشاء فئة تدير إحصائيات اللاعب مع التحقق المناسب. يجب أن يقوم المنشئ:new(name)بتهيئة اللاعب باسم، وتعيين_healthإلى100، و_levelإلى1. قم بتضمين هذه الدوال::getName()— يرجع اسم اللاعب:getHealth()— يرجع الصحة الحالية:getLevel()— يرجع المستوى الحالي:setHealth(value)— يقوم بتحديث الصحة فقط إذا كانت القيمة بين 0 و 100 (شاملة). إذا كانت غير صالحة، اطبعError: Health must be between 0 and 100ولا تغير القيمة.:setLevel(value)— يقوم بتحديث المستوى فقط إذا كانت القيمة 1 أو أكبر. إذا كانت غير صالحة، اطبعError: Level must be at least 1ولا تغير القيمة.
main.lua: استدعِ وحدة Player الخاصة بك واقرأ اسم اللاعب، ثم قيمتين لاختبار دوال التعيين. أنشئ لاعباً، وحاول تعيين صحته إلى القيمة الأولى، وحاول تعيين مستواه إلى القيمة الثانية، ثم اطبع إحصائيات اللاعب النهائية.
ستتلقى ثلاثة مدخلات:
- اسم اللاعب
- قيمة الصحة لمحاولة تعيينها (رقم، قد يكون صالحاً أو غير صالح)
- قيمة المستوى لمحاولة تعيينها (رقم، قد يكون صالحاً أو غير صالح)
يجب أن يظهر مخرجك أي رسائل خطأ من المحاولات غير الصالحة، متبوعة بإحصائيات اللاعب النهائية:
Name: {name}
Health: {finalHealth}
Level: {finalLevel}على سبيل المثال، إذا كانت المدخلات هي Hero و -20 و 5، يجب أن يكون المخرج:
Error: Health must be between 0 and 100
Name: Hero
Health: 100
Level: 5رفضت دالة تعيين الصحة القيمة -20 (مع الإبقاء على الصحة عند 100)، بينما قبلت دالة تعيين المستوى القيمة 5 كقيمة صالحة.
إذا كانت المدخلات هي Warrior و 75 و 0، يجب أن يكون المخرج:
Error: Level must be at least 1
Name: Warrior
Health: 75
Level: 1ورقة مرجعية
تسمح لك دوال التعيين (Setter methods) بالتحقق من صحة البيانات قبل تحديث خصائص الكائن، مما يضمن قبول القيم الصالحة فقط.
دالة تعيين أساسية مع التحقق من الصحة:
function Person:setAge(newAge)
if newAge < 0 then
print("Error: Age cannot be negative")
return
end
self._age = newAge
endتعمل دالة التعيين كحارس بوابة—فهي تتحقق مما إذا كانت القيمة الجديدة صالحة قبل تحديث الخاصية الداخلية. إذا فشل التحقق من الصحة، فإنها تطبع خطأ وتتوقف مبكرًا دون تعديل البيانات.
يمكن أن يشمل التحقق من الصحة ما يلي:
- فحوصات النطاق (على سبيل المثال، age >= 0)
- حدود النطاق (على سبيل المثال، 0 <= health <= 100)
- التحقق من نوع البيانات
- التحقق من تنسيق البيانات
يمنع هذا البيانات غير الصالحة من إفساد حالة الكائن الخاص بك ويحافظ على اتساق برنامجك.
جرّب بنفسك
-- استدعاء وحدة Player
local Player = require('Player')
-- قراءة المدخلات
local name = io.read()
local healthValue = tonumber(io.read())
local levelValue = tonumber(io.read())
-- TODO: إنشاء لاعب جديد بالاسم المعطى
-- TODO: محاولة تعيين صحة اللاعب إلى healthValue
-- TODO: محاولة تعيين مستوى اللاعب إلى levelValue
-- TODO: طباعة إحصائيات اللاعب النهائية بالتنسيق التالي:
-- Name: {name}
-- Health: {finalHealth}
-- Level: {finalLevel}
يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.
جميع دروس Object Oriented Programming
4مشروع: بنك رقمي
إعداد المشروعطريقة الإيداع7تعدد الأشكال وإعادة التعريف
إعادة تعريف الدوالاستدعاء دوال الفئة الأبDuck Typingواجهة مشتركةالتحقق من النوعمراجعة - أدوار الموظفين2نمط النموذج الأولي للفئات
مفهوم النموذج الأوليالربط باستخدام __indexالمنشئ :new()تهيئة الخصائصنسخ مستقلةملخص - مصنع السيارات5تحميل المعاملات في OOP
جمع الكائناتطرح الكائناتدمج الكائناتمقارنة الكائنات (<, >)مراجعة - رياضيات المحفظة8التغليف
اصطلاحات التسميةاستخدام Closures للخصوصيةالوصول عبر Closuresجداول للقراءة فقطمنطق التحقق من الصحةمراجعة - الخزنة الآمنة11أنماط التصميم (مبسط)
دوال المصنعجدول Singletonنمط الـ Iteratorالمراقب (المستمع)مراجعة - مصنع الـ Logger3حالة الكائن وسلوكه
متغيرات النسخةدالات الجلب (Getter Methods)دالات التعيين (Setter Methods)الخصائص المحسوبةتنسيق النصوصالتحقق من المساواةمراجعة - درجة الطالب6أساسيات الوراثة
إعداد الوراثةوراثة الـ Methodsتوسيع الـ Constructorإضافة Methods للابنالمشترك مقابل الفريدملخص - التسلسل الهرمي للأشكال