الملاكمة (برمجة الكمبيوتر)

في علوم الحاسوب ، يُعرف التغليف (أو التغليف) بأنه عملية وضع نوع بيانات أولي داخل كائن بحيث يمكن استخدام قيمته كمرجع . أما فك التغليف فهو العملية العكسية لاستخراج قيمة النوع الأولي من الكائن المُغلِّف. ويُطلق مصطلح التغليف التلقائي على تطبيق عمليات التغليف و/أو فك التغليف تلقائيًا حسب الحاجة.

ملاكمة

يُستخدم التغليف (Boxing) بشكل أساسي في لغة جافا، حيث يوجد تمييز بين أنواع المراجع وأنواع القيم لأسبابٍ منها كفاءة وقت التشغيل ، بالإضافة إلى مسائل بناء الجملة والدلالات . في جافا، يجب أن يكون العنصر من النوع `<value>` نسخةً من ` <value> `. قد يرغب المستخدم في إنشاء `<value>` ، لكن هذا غير ممكن مباشرةً. بدلاً من ذلك، تُعرّف جافا فئات تغليف بدائية تُقابل كل نوع بدائي : `<value> ` و` < value>` و` <value >`، إلخ. باستخدام الأنواع المُعاملة العامة المُقدمة في منصة جافا القياسية (J2SE) 5.0، يُمكن تعريف `<value>` وإدراج القيم في القائمة عن طريق تغليفها ككائنات.LinkedList<T>TObjectLinkedList<int>IntegerintCharactercharFloatfloatLinkedList<Integer>intInteger

من ناحية أخرى، لا تحتوي لغة C# على فئات تغليف للأنواع الأولية، ولكنها تسمح بتحويل أي نوع قيمة إلى نوع تغليف، مع إرجاع Objectمرجع عام. في لغة Objective-C ، يمكن إضافة بادئة إلى أي قيمة أولية @لتحويلها NSNumberإلى نوع تغليف (مثلاً `<string>` @123أو `<string> `). يتيح ذلك إضافتها إلى أي من المجموعات القياسية، مثل `<string>` .@(123)NSArray

لا يمتلك هاسكل مفهومًا يُذكر عن نوع المرجع ، ولكنه لا يزال يستخدم مصطلح "مُغلّف" لتمثيل نظام وقت التشغيل الموحد للمؤشر إلى الاتحاد المُوسوم . [ 1 ]

الكائن المُغلّف هو دائمًا نسخة من كائن القيمة، وعادةً ما يكون غير قابل للتغيير . كما أن فك تغليف الكائن يُعيد نسخة من القيمة المُخزّنة. قد يُؤثّر تكرار تغليف وفك تغليف الكائنات سلبًا على الأداء، لأن التغليف يُخصّص كائنات جديدة ديناميكيًا، وفك التغليف (إذا لم تعد القيمة المُغلّفة مُستخدمة) يجعلها مُعرّضة لجمع البيانات المهملة . مع ذلك، تستطيع أدوات جمع البيانات المهملة الحديثة، مثل أداة جمع البيانات المهملة الافتراضية في Java HotSpot، جمع الكائنات قصيرة العمر بكفاءة أكبر، لذا إذا كانت الكائنات المُغلّفة قصيرة العمر، فقد لا يكون تأثير الأداء كبيرًا.

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

نظام الدفع التلقائي

التحويل التلقائي للأنواع هو مصطلح يُستخدم لوصف استخراج نوع مرجعي من نوع قيمة بمجرد تحويل النوع (سواء كان ضمنيًا أو صريحًا). يقوم المترجم تلقائيًا بتوفير الشيفرة المصدرية الإضافية اللازمة لإنشاء الكائن.

على سبيل المثال، في إصدارات جافا السابقة لـ J2SE 5.0، لم يتم تجميع الكود التالي:

Integer i = new Integer ( 9 ); Integer i = 9 ; // خطأ في الإصدارات السابقة للإصدار 5.0!

لم تكن المترجمات قبل الإصدار 5.0 تقبل السطر الأخير. هي كائنات مرجعية، لا تختلف ظاهريًا عن و وما إلى ذلك. لتحويل من إلى ، كان يجب إنشاء كائن Integer يدويًا. بدءًا من J2SE 5.0، سيقبل المترجم السطر الأخير، ويحوله تلقائيًا لإنشاء كائن Integer لتخزين القيمة . [ 2 ] هذا يعني أنه بدءًا من J2SE 5.0، سيتم تجميع شيء مثل ، حيث و هما بالفعل - يتم فك تغليف a و b، وجمع قيم الأعداد الصحيحة، ثم يتم تغليف النتيجة تلقائيًا في كائن جديد ، والذي يتم تخزينه أخيرًا داخل المتغير . لا يمكن استخدام عوامل المساواة بهذه الطريقة، لأنها مُعرّفة بالفعل لأنواع المراجع، لمساواة المراجع؛ لاختبار مساواة القيمة في نوع مُغلّف، يجب فك تغليفها يدويًا ومقارنة القيم الأولية، أو استخدام الطريقة .IntegerListObjectintInteger9Integerc=a+babIntegerIntegercObjects.equals

مثال آخر: يسمح J2SE 5.0 للمبرمج بالتعامل مع مجموعة (مثل `<a>` ) كما لو كانت تحتوي على قيم بدلاً من كائنات. هذا لا يتعارض مع ما ذُكر سابقًا: فالمجموعة لا تزال تحتوي فقط على مراجع لكائنات ديناميكية، ولا يمكنها سرد أنواع البيانات الأولية. لا يمكن أن تكون `<a>` ، بل يجب أن تكون `<a>` . مع ذلك، يقوم المُصرّف تلقائيًا بتحويل الكود بحيث تستقبل القائمة `<a>` كائنات "بصمت"، بينما يذكر الكود المصدري القيم الأولية فقط. على سبيل المثال، يمكن للمبرمج الآن كتابة الكود والتفكير كما لو تمت إضافة `<a>` إلى القائمة؛ لكن المُصرّف سيُحوّل السطر فعليًا إلى `<a>` .LinkedListintIntegerLinkedList<int>LinkedList<Integer>list.add(3)int3list.add(newInteger(3))

فتح العلبة تلقائياً

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

على سبيل المثال، في إصدارات جافا السابقة لـ J2SE 5.0، لم يتم تجميع الكود التالي:

Integer k = new Integer ( 4 ); int l = k.intValue ( ); // صحيح دائمًا int m = k ; // كان سيُسبب خطأً، لكنه صحيح الآن

لا تدعم لغة C# فك التغليف التلقائي بنفس معنى لغة Java، لأنها لا تحتوي على مجموعة منفصلة من الأنواع الأولية وأنواع الكائنات. جميع الأنواع التي لها إصدارات أولية وأخرى كائنية في Java، يتم تنفيذها تلقائيًا بواسطة مُصرّف C# إما كأنواع أولية (قيم) أو كأنواع كائنية (مرجعية).

في كلتا اللغتين، لا يقوم التحويل التلقائي للأنواع بتحويل الأنواع إلى أنواع فرعية تلقائيًا، أي أن الكود التالي لن يتم تجميعه:

سي شارب:

int i = 42 ; object o = i ; // تغليف int j = o ; // فك التغليف (خطأ) Console.WriteLine ( j ) ; // سطر غير قابل للوصول، ربما توقع المؤلف الناتج "42"

جافا:

int i = 42 ; Object o = i ; // تغليف int j = o ; // فك التغليف (خطأ) System.out.println ( j ) ; // سطر غير قابل للوصول ، ربما توقع المؤلف الناتج "42 "

الملاكمة في الصدأ

يحتوي RustBox على النوع الذي يمثل قيمة مملوكة بشكل فريد ومخصصة في الذاكرة الديناميكية: [ 3 ]

let number : Box < i32 > = Box :: new ( 42 );

std::boxed::Boxفي لغة Rust يعادل std::unique_ptrفي لغة C++ ، وهو نوع من المؤشر الذكي .

باستخدام std :: unique_ptr ؛unique_ptr < int > number = std :: make_unique < int > ( 42 );

إذا كانت القيمة بحاجة إلى ملكية مشتركة (مثلاً بين الخيوط)، فيمكن استخدام `<input>` Arc، الذي يمثل قيمة مُخصصة في الذاكرة الديناميكية مع عدّ المراجع. [ 4 ] [ 5 ] وهذا مشابه لـ `<input>` std::shared_ptrفي لغة C++.

مساعدو الكتابة

يحتوي Modern Object Pascal على طريقة أخرى لإجراء العمليات على الأنواع البسيطة، قريبة من التغليف، تسمى مساعدي النوع في Free Pascal أو مساعدي السجل في Delphi و Free Pascal في وضع Delphi.

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

لكن هذه الخاصية مرتبطة بالملاكمة. فهي تسمح باستخدام تركيبات مثل:

{$ifdef fpc}{$mode delphi}{$endif} uses sysutils ; // تحتوي هذه الوحدة على أغلفة للأنواع البسيطة var x : integer = 100 ; s : string ; begin s := x . ToString ; writeln ( s ) ; end .

مراجع

  1. "7.2. الأنواع غير المعبأة والعمليات الأولية" . downloads.haskell.org . تم الاطلاع عليه بتاريخ 10 أغسطس 2022 .
  2. دليل لغة جافا على موقع أوراكل (oracle.com) حول التغليف التلقائي
  3. "std::boxed - Rust" . doc.rust-lang.org . تم الاطلاع عليه في 2 يونيو 2025 .
  4. "Arc in std::sync - Rust" . doc.rust-lang.org . تم الاطلاع عليه بتاريخ 18 يناير 2025 .
  5. "Arc - Rust By Example" . doc.rust-lang.org . تم الاطلاع عليه بتاريخ 18 يناير 2025 .