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

إخفاء المعلومات في Go

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

يتجاوز إخفاء المعلومات مجرد جعل fields غير مُصدَّرة. إنه يتعلق بتصميم أنواعك بحيث لا تعرف الشيفرة الخارجية سوى ما تحتاج إلى معرفته. لا شيء أكثر من ذلك.

الهدف هو إتاحة السلوك من خلال الأساليب مع إبقاء البنية الداخلية مخفية تمامًا. Consider هذا النهج:

type Counter struct {
    value    int
    maxLimit int
}

func NewCounter(limit int) *Counter {
    return &Counter{maxLimit: limit}
}

func (c *Counter) Increment() bool {
    if c.value >= c.maxLimit {
        return false
    }
    c.value++
    return true
}

func (c *Counter) Value() int {
    return c.value
}

لا تعرف الشيفرة الخارجية أن Counter تستخدم int داخليًا. قد تكون float64، أو شريحة، أو شيئًا آخر تمامًا. يمكن أن تتغير implementation دون التأثير في أي شيفرة تستخدم Counter، ما دامت الأساليب تتصرف بالطريقة نفسها.

ينطبق هذا المبدأ أيضًا على helper functions. أبقِ internal logic غير مُصدَّر:

// مُصدَّر - جزء من واجهة برمجة التطبيقات العامة
func (c *Counter) Reset() {
    c.value = 0
}

// غير مُصدَّر - مساعد داخلي
func (c *Counter) isAtLimit() bool {
    return c.value >= c.maxLimit
}

من خلال إخفاء isAtLimit()، تصبح حرًّا في تغييره أو إزالته لاحقًا. ينشئ إخفاء المعلومات حدًّا واضحًا بين ما يعد به الحِزْمَة للمستخدمين الخارجيين وكيفية عملها داخليًا.

challenge icon

التحدي

سهل

لنبنِ نظام محفظة آمنة يوضّح إخفاء المعلومات. ستنشئ محفظة digital حيث يتم إخفاء تتبّع balance الداخلي وسجل المعاملات بالكامل عن الكود الخارجي: لا يتم كشف سوى السلوك من خلال الأساليب.

ستنظّم الكود الخاص بك عبر ملفين:

  • wallet.go: أنشئ بنية Wallet تخفي كل حالتها الداخلية. يجب أن تتتبّع المحفظة قيمة balance الحالية وحدّ الإنفاق داخليًا، لكن يجب ألا يعرف الكود الخارجي أبدًا كيفية تخزين هذه القيم أو تمثيلها. اكشف السلوك من خلال هذه الأساليب:
    • NewWallet(limit float64) *Wallet - constructor ينشئ محفظة باستخدام حدّ الإنفاق given وbalance يساوي صفرًا
    • Deposit(amount float64) bool - يضيف المال إلى المحفظة، ويُرجع true إذا نجحت العملية (يجب أن تكون amount موجبة)
    • Spend(amount float64) bool - يزيل المال إذا كان balance كافيًا AND لم تتجاوز amount حدّ الإنفاق، ويُرجع true إذا نجحت العملية
    • Balance() float64 - يُرجع قيمة balance الحالية
    • Status() string - يُرجع رسالة حالة بالتنسيق: Balance: $[balance] (Limit: $[limit])
    احتفظ بأي منطق helper (مثل التحقق مما إذا كانت المعاملة صالحة) على هيئة functions أو أساليب غير مُصدَّرة. هذه details من implementation internal التي قد تتغير لاحقًا.
  • main.go: اقرأ إعدادات المحفظة والمعاملات من inputs، وأنشئ محفظة، ونفّذ العمليات، واعرض النتائج بعد كل إجراء.

سيتم توفير inputs التالية:

  • السطر 1: Limit الإنفاق
  • السطر 2: Deposit amount
  • السطر 3: First spend amount
  • السطر 4: Second spend amount

بعد إنشاء المحفظة، اطبع حالتها initial. ثم نفّذ كل عملية واطبع إما الحالة المحدّثة (إذا نجحت) أو Transaction failed (إذا تم رفض العملية). نسّق جميع المبالغ بالدولار باستخدام منزلتين عشريتين.

على سبيل المثال، given 50 و100 و30 و80، يجب أن يكون الناتج:

Balance: $0.00 (Limit: $50.00)
Balance: $100.00 (Limit: $50.00)
Balance: $70.00 (Limit: $50.00)
Transaction failed

تفشل المعاملة الأخيرة لأن $80 تتجاوز حدّ الإنفاق البالغ $50، رغم وجود balance كافٍ. تفرض المحفظة قواعدها داخليًا دون كشف كيفية اتخاذها لهذه القرارات. يستدعي الكود الخارجي الأساليب ببساطة ويتلقى النتائج، دون أن يعرف أبدًا تفاصيل implementation الداخلية.

جرّب بنفسك

package main

import (
	"fmt"
)

func main() {
	// اقرأ المدخلات
	var limit float64
	var depositAmount float64
	var spend1 float64
	var spend2 float64

	fmt.Scanln(&limit)
	fmt.Scanln(&depositAmount)
	fmt.Scanln(&spend1)
	fmt.Scanln(&spend2)

	// TODO: أنشئ محفظة جديدة بحد الإنفاق المعطى

	// TODO: اطبع الحالة الأولية

	// TODO: Perform deposit and print result (status or "Transaction failed")

	// TODO: نفّذ الإنفاق الأول واطبع النتيجة

	// TODO: نفّذ الإنفاق الثاني واطبع النتيجة
}
quiz iconاختبر نفسك

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

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

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