نوع القيمة ونوع المرجع

في بعض لغات برمجة الحاسوب ، تُصنف أنواع البيانات إما إلى أنواع قيم أو أنواع مرجعية ، حيث يتم الوصول إلى القيم التي تشير إليها متغيرات النوع المرجعي ضمنيًا دائمًا عبر المراجع المخزنة في تلك المتغيرات، بينما تحتوي متغيرات النوع القيمي مباشرةً على القيم نفسها. [ 1 ] [ 2 ]

خصائص أنواع القيم وأنواع المراجع

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

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

أنواع المراجع و"الاتصال عن طريق المشاركة"

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

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

أنواع المراجع مقابل المؤشرات الصريحة

تحتوي العديد من اللغات على مؤشرات أو مراجع صريحة . تختلف أنواع المراجع عن هذه في أن الكيانات التي تشير إليها يتم الوصول إليها دائمًا عبر المراجع؛ على سبيل المثال، بينما في لغة C++ من الممكن أن يكون لدينا إما `a` و`a` ، حيث يكون الأول سلسلة قابلة للتغيير والثاني مؤشرًا صريحًا إلى سلسلة قابلة للتغيير (إلا إذا كان مؤشرًا فارغًا )، في لغة Java من الممكن فقط أن يكون لدينا `a` ، وهو مرجع ضمني إلى سلسلة قابلة للتغيير (إلا إذا كان مرجعًا فارغًا).std::stringstd::string*StringBuilder

على الرغم من أن نهج C++ أكثر مرونة، إلا أن استخدام غير المراجع يمكن أن يؤدي إلى مشاكل مثل تقطيع الكائنات ، على الأقل عند استخدام الوراثة ؛ في اللغات التي تنتمي فيها الكائنات إلى أنواع مرجعية، يتم تجنب هذه المشاكل تلقائيًا، على حساب إزالة بعض الخيارات من المبرمج.

إعادة ربط المراجع والأسماء المستعارة

في معظم لغات البرمجة، من الممكن تغيير متغير من نوع مرجعي للإشارة إلى كائن آخر، أي إعادة ربط المتغير بكائن آخر.

على سبيل المثال، في كود جافا التالي:

class Foo { public int a ; }Foo a = new Foo ( ) ; Foo b = a ; a.prop = 3 ; a = new Foo ( ) ; a.prop = 1 ;

Fooهو نوع مرجعي، حيث aيُسند إليه في البداية مرجع لكائن جديد، bويُسند إليه نفس مرجع الكائن، أي يرتبط بنفس الكائن الذي يرتبط به a، وبالتالي، فإن التغييرات التي تطرأ عليه aتكون مرئية له bأيضًا. بعد ذلك، aيُسند إليه مرجع (إعادة ربط) لكائن جديد آخر، ويشير كل من و aإلى bكائنين مختلفين. في النهاية، aيشير إلى الكائن الثاني propبقيمة 1، بينما bيشير إلى الكائن الأول propبقيمة 3.

ومع ذلك، كما هو الحال في لغة C++، فإن مصطلح "نوع المرجع" يستخدم بمعنى الاسم المستعار، ولا يمكن إعادة ربط متغير من نوع مرجع بمجرد إنشائه، لأنه اسم مستعار للكائن الأصلي.

class Foo { public : int a ; };Foo a ; a . prop = 1 ; Foo & b = a ; Foo c = a ; a . prop = 3 ;

في لغة C++، تتمتع جميع أنواع الفئات غير المرجعية بدلالات القيمة. في المثال أعلاه، bتم تعريف `is` على أنه مرجع (اسم بديل) لـ `a` a، ولجميع الأغراض، يُعتبر `is` aو` ba` الشيء نفسه. من المستحيل إعادة ربط ` bis` ليصبح شيئًا آخر. بعد تشغيل المثال أعلاه، يصبح ` is` aو` ba` نفس Fooالكائن حيث ` propis` هو `a` 3، بينما ` cis` هو نسخة من الكائن الأصلي aحيث ` propis` هو `a` 1.

في لغة C#، بالإضافة إلى التمييز بين أنواع القيم وأنواع المراجع، يوجد مفهوم منفصل يُسمى متغيرات المراجع. [ 3 ] يعمل متغير المرجع، بمجرد تعريفه وربطه، كاسم بديل للمتغير الأصلي، ولكن يمكن أيضًا ربطه بمتغير آخر باستخدام عامل إسناد المرجع = ref. يمكن أن يكون المتغير نفسه من أي نوع، بما في ذلك أنواع القيم وأنواع المراجع، أي بتمرير متغير من نوع مرجعي بالمرجع (اسم بديل) إلى دالة، يمكن أيضًا تغيير الكائن الذي يشير إليه متغير نوع المرجع، بالإضافة إلى الكائن نفسه (إذا كان قابلاً للتغيير).

أنواع البيانات غير القابلة للتغيير

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

التصنيف حسب اللغة

لغةنوع القيمةنوع المرجع
جافا [ 4 ]جميع الأنواع غير الكائنية، بما في ذلك (على سبيل المثال) القيم المنطقية والأرقام (تم اقتراح دعم أنواع قيم الكائنات لمشروع فالهالا )جميع أنواع الكائنات، بما في ذلك (على سبيل المثال) المصفوفات
لغة سي++جميع أنواع البيانات، باستثناء أنواع المراجع وأنواع المصفوفات وأنواع الدوال.المصفوفات والدوال
سي شارب [ 5 ]جميع الأنواع غير الكائنية، بما في ذلك الهياكل والتعدادات بالإضافة إلى الأنواع الأوليةجميع أنواع الكائنات، بما في ذلك الفئات والواجهات
سويفت [ 6 ] [ 7 ]الهياكل (بما في ذلك على سبيل المثال القيم المنطقية والأرقام والسلاسل والمجموعات) والتعدادات (بما في ذلك على سبيل المثال القيم الاختيارية)الدوال، والإغلاقات، والفئات
بايثون [ 8 ]جميع الأنواع
جافا سكريبت [ 9 ]جميع الكائنات غير الكائنية، بما في ذلك القيم المنطقية، والأعداد العشرية، والسلاسل النصية، من بين أمور أخرى.جميع الكائنات، بما في ذلك الدوال والمصفوفات، من بين أمور أخرى
الصدأ [ 10 ]جميع الأنواع التي تُنفذ سمة النسخجميع الأنواع التي لا تُطبّق سمة النسخ
OCaml [ 11 ] [ 12 ]الأحرف غير القابلة للتغيير، والأعداد الصحيحة غير القابلة للتغيير، والأعداد العشرية غير القابلة للتغيير، والصفوف غير القابلة للتغيير، والتعدادات غير القابلة للتغيير (بما في ذلك الوحدات غير القابلة للتغيير، والقيم المنطقية غير القابلة للتغيير، والقوائم غير القابلة للتغيير، والقيم الاختيارية غير القابلة للتغيير)، والاستثناءات غير القابلة للتغيير، وسلاسل التنسيق غير القابلة للتغييرالمصفوفات، السلاسل النصية غير القابلة للتغيير، سلاسل البايت، القواميس
PHPالأنواع غير الكائنية، مثل الأنواع الأولية والمصفوفات.جميع أنواع الكائنات (الفئات) [ 13 ]

انظر أيضاً

مراجع