Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

جداول للقراءة فقط

جزء من قسم البرمجة كائنية التوجه في رحلة Lua على Coddy. الدرس 46 من 70.

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

تت intercept metamethod __newindex محاولات تعيين قيم جديدة إلى جدول. ومن خلال جعله يحظر all عمليات التعيين، يمكنك تجميد object:

local ImmutablePoint = {}

function ImmutablePoint.new(x, y)
    local data = {x = x, y = y}
    
    local proxy = {}
    setmetatable(proxy, {
        __index = data,
        __newindex = function()
            error("Cannot modify immutable object")
        end
    })
    
    return proxy
end

الحيلة هي استخدام جدول وكيل. توجد البيانات الفعلية في data، بينما يتفاعل المستخدم مع proxy الفارغ.

عند القراءة، تجلب __index البيانات من data. وعند الكتابة، تُستدعى __newindex بدلًا من ذلك، ونحظرها:

local p = ImmutablePoint.new(10, 20)
print(p.x)  -- 10 (القراءة تعمل)
p.x = 50    -- خطأ: لا يمكن تعديل كائن غير قابل للتغيير

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

challenge icon

التحدي

سهل

لنبنِ فئة ImmutableConfig تنشئ كائنات إعدادات للقراءة فقط! بعد إنشائها، يجب أن تسمح كائنات الإعدادات هذه بقراءة إعداداتها، لكنها تمنع تمامًا أي محاولات لتعديلها.

ستنظّم الشيفرة عبر ملفين:

  • ImmutableConfig.lua: أنشئ وحدة تنتج كائنات إعدادات مجمّدة. يجب أن تخزّن دالة .new(appName, version, maxUsers) هذه القيم الثلاث داخليًا، ثم تعيد جدولًا وسيطًا يسمح بقراءة جميع الحقول، لكنه يمنع أي تعديلات. عندما يحاول أحدهم تغيير قيمة، يجب أن تطبع Error: Config is read-only بدلًا من رفع خطأ فعلي.
  • main.lua: فعّل ImmutableConfig! اقرأ ثلاث مدخلات لقيم الإعدادات، وأنشئ كائن إعدادات، ثم أثبت أنه يعمل بشكل صحيح من خلال:
    • طباعة القيم الأصلية الثلاث
    • محاولة تعديل الحقل maxUsers (وهو ما يجب أن يطلق رسالة الخطأ)
    • طباعة maxUsers مرة أخرى لإثبات أنه لم يتغير فعليًا

ستتلقى ثلاث مدخلات:

  1. اسم التطبيق (سلسلة نصية)
  2. الإصدار (سلسلة نصية)
  3. الحد الأقصى للمستخدمين (عدد)

يجب أن يُظهر الناتج قيم الإعدادات، والخطأ عند محاولة التعديل، والتأكيد على أن القيمة بقيت دون تغيير:

App: {appName}
Version: {version}
Max Users: {maxUsers}
Error: Config is read-only
Max Users: {maxUsers}

على سبيل المثال، إذا كانت المدخلات هي MyApp و2.0 و100، فيجب أن يكون الناتج:

App: MyApp
Version: 2.0
Max Users: 100
Error: Config is read-only
Max Users: 100

تذكّر: يستخدم نمط الجدول الوسيط جدولًا فارغًا يتفاعل معه المستخدم، بينما توجد البيانات الفعلية في جدول داخلي منفصل. تستجلب دالة metamethod __index البيانات من جدول البيانات، وتعترض __newindex أي محاولات كتابة (وتمنعها)!

جرّب بنفسك

-- استيراد وحدة ImmutableConfig
local ImmutableConfig = require('ImmutableConfig')

-- اقرأ المدخلات
local appName = io.read()
local version = io.read()
local maxUsers = tonumber(io.read())

-- TODO: أنشئ كائن config باستخدام ImmutableConfig.new()

-- TODO: اطبع القيم الأصلية الثلاث بالتنسيق:
-- التطبيق: {appName}
-- الإصدار: {version}
-- أقصى المستخدمين: {maxUsers}

-- TODO: حاول تعديل حقل maxUsers (هذا يجب أن يطلق رسالة خطأ)

-- TODO: اطبع maxUsers مرة أخرى لإثبات أنه لم يتغير
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس البرمجة كائنية التوجه

تدرّب بنفسك: مترجم Lua عبر الإنترنت