الربط الثابت والربط الديناميكي
في الآونة الأخيرة ، تعلمت المعرفة Java وتعلمت الربط الثابت والديناميكي لـ Java. ثم قمت بتلخيص وفرز المعرفة المقابلة على Baidu للمساعدة في إتقان هذا الجزء من المعرفة.
مفهوم ملزمة البرنامج:
يشير الربط إلى ارتباط استدعاء الطريقة مع الفصل (جسم الطريقة) حيث توجد الطريقة. بالنسبة إلى Java ، يتم تقسيم الربط إلى ربط ثابت وربط ديناميكي ؛ أو يسمى الربط المبكر والربط المتأخر.
ملزمة ثابت:
يتم ربط هذه الطريقة قبل تنفيذ البرنامج (أي ، أنت تعرف بالفعل الفئة الموجودة في عملية التجميع) ، ويتم تنفيذها بواسطة برنامج التحويل البرمجي أو برامج التوصيل الأخرى. على سبيل المثال: C.
يمكن فهمه ببساطة على أنه ملزم خلال فترة تجميع البرنامج لـ Java ؛ فيما يلي بشكل خاص أن الأساليب الوحيدة في جافا هي النهائيات والثابتة والخاصة والمؤسسين الذين يتم ربطهم مسبقًا
الربط الديناميكي:
الربط لاحقًا: يربط وفقًا لنوع الكائن المحدد في وقت التشغيل.
إذا كانت اللغة تنفذ الربط المتأخر ، فيجب أن توفر أيضًا بعض الآليات لتحديد نوع الكائن أثناء التشغيل واستدعاء الطرق المناسبة بشكل منفصل. بمعنى آخر ، لا يزال المترجم لا يعرف نوع الكائن في هذا الوقت ، ولكن يمكن أن تحقق آلية استدعاء الطريقة في حد ذاتها وإيجاد هيكل الطريقة الصحيحة. اللغات المختلفة لها طرق مختلفة لتنفيذ الربط المتأخر. ولكن يمكننا على الأقل التفكير بهذه الطريقة: كلهم بحاجة إلى تثبيت أنواع خاصة من المعلومات في الكائن.
عملية الربط الديناميكي:
النهائي ، الثابت ، الخاص والمنشئون هم فهم الربط المبكر
بالنسبة للطريقة الخاصة ، أولاً وقبل كل شيء ، لا يمكن موروثة. نظرًا لأنه لا يمكن موروثة ، فلا توجد طريقة لاستدعاءها من خلال كائن فئة الفئة الفرعية الخاصة به ، ولكن لا يمكن استدعاؤها إلا من خلال كائن هذه الفئة نفسها. لذلك ، يمكن القول أن الطريقة الخاصة مرتبطة بالفئة التي تحدد هذه الطريقة.
على الرغم من أن الطريقة النهائية يمكن موروثة ، لا يمكن الكتابة فوقها (تجاوز). على الرغم من أنه يمكن استدعاء كائن فئة الطفل ، إلا أن الطريقة النهائية المحددة في الفئة الأصل تسمى (من هذا يمكننا أن نعرف أن الطريقة يتم الإعلان عنها كنوع نهائي ، والآخر هو منع الكتابة فوقها ، والآخر هو إغلاق الربط الديناميكي بشكل فعال في Java).
لا يمكن مورث المنشئين (هناك أيضًا قول أن الفئات الفرعية ترث دون قيد أو شرط عن مُنشئ الفئة الوالد غير المعلمة كمنشئهم ، لكنني شخصياً أعتقد أن هذا البيان غير مناسب ، لأننا لا نعلم أن الفئات الفرعية تستدعي ذلك من خلال أن تكون الطبقة الوالدة غير المثيرة للميرا حتى لا تقل عن ذلك ، فهو يجب أن يقل عن ذلك ، لا ينبغي القول أنه لا ينبغي أن يقال مُنشئ الطبقة). لذلك ، يمكنك أيضًا معرفة الفئة التي ينتمي إليها هذا المنشئ عند التجميع.
لا أستطيع أن أشرح المبادئ المحددة للطريقة الثابتة جيدًا. ومع ذلك ، استنادًا إلى المعلومات عبر الإنترنت وتجربتي الخاصة ، يمكننا أن نستنتج أن الطريقة الثابتة يمكن أن ترثها الفئات الفرعية ، ولكن لا يمكن إعادة كتابتها (تجاوزات) بواسطة الفئات الفرعية ، ولكن يمكن إخفاؤها بواسطة الفئات الفرعية. (هذا يعني أنه إذا كانت هناك طريقة ثابتة في الفئة الأصل ، وإذا لم تكن هناك طريقة مقابلة في فدريتها الفرعية ، فسيتم استخدام الطريقة في الفئة الأصل عندما يستدعي كائن فئة الطفل هذه الطريقة. وإذا تم تحديد الطريقة نفسها في فئة الوالد ، فسيتم تحديد الطريقة التي يتم تحديدها في فئة الطفل. فئة الوالدين بغض النظر عما إذا كان لدى فئة الطفل هذه الطريقة الثابتة.
مما سبق ، يمكننا أن نستنتج أنه إذا لم يكن من الممكن مورث الطريقة أو لا يمكن الكتابة فوقها بعد الميراث ، فإن هذه الطريقة تعتمد الربط الثابت.
تجميع وتشغيل Java
عملية تجميع Java هي عملية تجميع ملف مصدر Java في Bytecode (الرمز القابل للتنفيذ JVM ، أي ملف .class). في هذه العملية ، لا تتعامل Java مع الذاكرة. في هذه العملية ، سيقوم برنامج التحويل البرمجي بتحليل بناء الجملة. إذا كان بناء الجملة غير صحيح ، فسيتم الإبلاغ عن خطأ.
تشير عملية تشغيل Java إلى JVM (Java Virtual Machine) تحميل ملفات Bytecode وتفسير التنفيذ. في هذه العملية ، هو إنشاء تخطيط الذاكرة وتنفيذ برامج Java الحقيقية.
هناك طريقتان لتنفيذ Java Bytecode: (1) طريقة التجميع الفورية: يقوم المترجم أولاً بتجميع البايتات في رمز الجهاز ، ثم ينفذ رمز الجهاز ؛ (2) طريقة تنفيذ التفسير: يكمل المترجم المترجم جميع عمليات برنامج Java Bytecode من خلال تفسير وتنفيذ جزء صغير من التعليمات البرمجية في كل مرة. (هنا يمكننا أن نرى أن برنامج Java يخضع بالفعل لتحويلين أثناء عملية التنفيذ ، تم تحويله لأول مرة إلى رمز Bytecode ثم تحويله إلى رمز الجهاز. وهذا أيضًا هو السبب في أنه يمكن تجميع Java وتشغيله في كل مكان في واحدة.
كما ذكرنا سابقًا ، بالنسبة للطرق الموجودة في Java ، باستثناء المُنشئين النهائيين والخاصين والمنشدين المبكرين ، فإن جميع الطرق الأخرى هي روابط ديناميكية.
يحدث الربط الديناميكي النموذجي بموجب إعلان تحويل الفئة الأم وفئة الطفل:
على سبيل المثال: الوالد p = الأطفال الجدد () ؛
تفاصيل العملية المحددة هي كما يلي:
1: يتحقق المترجم من نوع الإعلان واسم طريقة الكائن.
لنفترض أننا نسمي طريقة XF (args) وتم الإعلان عن X ككائن للفئة C ، ثم سرد المترجم جميع الطرق المسمى F في أساليب الفئة C و F الموروثة من الطبقة الفائقة من الفئة C.
2: بعد ذلك ، يتحقق برنامج التحويل البرمجي من نوع المعلمة المقدم في استدعاء الطريقة.
إذا كان نوع المعلمة واحد بين جميع الطرق مع الاسم F يطابق نوع المعلمة المقدمة من المكالمة أكثر ، فسيتم استدعاء هذه الطريقة. وتسمى هذه العملية "دقة الحمل الزائد".
3: عندما يقوم البرنامج بتشغيل ويستخدم الربط الديناميكي لطرق الاتصال ، يجب على الجهاز الظاهري استدعاء إصدار الطريقة الذي يتطابق مع النوع الفعلي للكائن الذي يشير إليه X.
افترض أن النوع الفعلي هو d (فئة فرعية من C) ، إذا كانت الفئة D تحدد F (سلسلة) ، فسيتم استدعاء الطريقة ، وإلا سيتم البحث عن الطريقة F (السلسلة) في الفئة الخارقة لـ D ، وهكذا.
عندما يستدعي جهاز Java Virtual طريقة فئة (طريقة ثابتة) ، فإنه يحدد الطريقة المسمى بناءً على نوع مرجع الكائن (المعروف عادة في وقت الترجمة). على العكس من ذلك ، عندما يقوم جهاز افتراضي باستدعاء طريقة مثيل ، فسيتم تحديد الطريقة المدعومة استنادًا إلى النوع الفعلي للكائن (المعروف فقط في وقت التشغيل). هذا هو الربط الديناميكي ، وهو نوع من الأشكال. يوفر الربط الديناميكي مرونة كبيرة لحل مشاكل العمل الفعلية وهو آلية جميلة للغاية.
على عكس الطرق ، عند التعامل مع متغيرات الأعضاء (متغيرات المثيل ومتغيرات الفئة) في فئات Java ، فإنه ليس ملزمًا وقت التشغيل ، ولكنه ملزم ثابت بالمعنى العام. لذلك في حالة التحول الأعلى ، يمكن أن تجد طريقة الكائن الفئة الفرعية ، في حين أن سمة الكائن (متغير العضو) لا تزال سمة الفئة الأصل (يختبئ الفئة الفرعية من متغير عضو الفئة الأصل).
فئة عامة الأب {name string المحمي = "سمة الأب" ؛ } SON الفئة العامة يمتد الأب {name string المحمي = "سمة الابن" ؛ public static void main (string [] args) {الأب عينة = new son () ؛ System.out.println ("Property:" + sample.name) ؛ }} الخلاصة: المتصل هو سمة الأب.
توضح هذه النتيجة أن كائن فئة الطفل (المقبض المرجعي لفئة الأصل) يتم استدعاؤه إلى متغير عضو الفئة الأصل. لذلك ، يجب أن يكون من الواضح أن الفئة التي تستهدف وقت التشغيل (الديناميكي) الربط ليست سوى طريقة كائن.
الآن تحاول الاتصال باسم متغير عضو الفئة الفرعية ، كيف تفعل ذلك؟ أسهل طريقة هي تغليف متغير العضو في نموذج getter طريقة.
الرمز كما يلي:
فئة عامة الأب {name string المحمي = "سمة الأب" ؛ السلسلة العامة getName () {return name ؛ }} SON الفئة العامة يمتد الأب {name string المحمي = "سمة الابن" ؛ السلسلة العامة getName () {return name ؛ } public static void main (string [] args) {الأب عينة = new son () ؛ System.out.println ("Property:" + sample.getName ()) ؛ }} النتيجة: تسمى سمة الابن
لماذا تعتمد Java طرق ربط ثابتة للسمات؟ وذلك لأن الربط الثابت له العديد من الفوائد ، مما يسمح لنا باكتشاف الأخطاء في البرنامج خلال فترة التجميع ، وليس خلال فترة التشغيل. سيؤدي ذلك إلى تحسين كفاءة تشغيل البرنامج! الربط الديناميكي للطرق هو تنفيذ تعدد الأشكال ، وهو ميزة رئيسية في Java. تعدد الأشكال هو أيضًا أحد التقنيات الرئيسية الموجهة للكائنات ، لذلك من المفيد أن تنفذ Java تعدد الأشكال على حساب الكفاءة.
ملاحظة: يأتي معظم المحتوى أعلاه من الإنترنت ، والجزء الصغير هو رأي شخصي ولا توجد ملاحظات موثوقة بأي حال من الأحوال. إذا كان هناك أي لغة غير لائقة أو تعبير غير صحيح ، آمل أن أقدم لكم النصيحة.
شكرا لك على القراءة ، آمل أن تساعدك. شكرا لك على دعمك لهذا الموقع!