JavaRush /مدونة جافا /Random-AR /تعدد الأشكال وأصدقائه
Viacheslav
مستوى

تعدد الأشكال وأصدقائه

نشرت في المجموعة
يعد تعدد الأشكال أحد المبادئ الأساسية للبرمجة الشيئية. فهو يتيح لك الاستفادة من قوة الكتابة القوية في Java وكتابة تعليمات برمجية قابلة للاستخدام والصيانة. لقد قيل الكثير عنه، لكني آمل أن يتمكن الجميع من استخلاص شيء جديد من هذه المراجعة.
تعدد الأشكال وأصدقائه - 1

مقدمة

أعتقد أننا جميعًا نعلم أن لغة برمجة Java تنتمي إلى شركة Oracle. ولذلك فإن طريقنا يبدأ بالموقع: www.Oracle.com . هناك "القائمة" على الصفحة الرئيسية. يوجد فيه قسم "الوثائق" قسم فرعي "Java". كل ما يتعلق بالوظائف الأساسية للغة ينتمي إلى "وثائق Java SE"، لذلك نختار هذا القسم. سيتم فتح قسم الوثائق لأحدث إصدار، ولكن في الوقت الحالي "هل تبحث عن إصدار مختلف؟" دعنا نختار الخيار: JDK8. سنرى على الصفحة العديد من الخيارات المختلفة. لكننا مهتمون بتعلم اللغة: " مسارات تعلم برامج Java التعليمية ". سنجد في هذه الصفحة قسمًا آخر: " تعلم لغة جافا ". هذا هو أقدس الأقداس، برنامج تعليمي حول أساسيات Java من Oracle. Java هي لغة برمجة كائنية التوجه (OOP)، لذا فإن تعلم اللغة حتى على موقع Oracle الإلكتروني يبدأ بمناقشة المفاهيم الأساسية لـ " مفاهيم البرمجة كائنية التوجه ". يتضح من الاسم نفسه أن Java تركز على العمل مع الكائنات. من القسم الفرعي " ما هو الكائن؟ "، من الواضح أن الكائنات في Java تتكون من الحالة والسلوك. تخيل أن لدينا حسابًا مصرفيًا. مبلغ المال في الحساب هو حالة، وطرق العمل مع هذه الحالة هي السلوك. يجب وصف الكائنات بطريقة ما (إخبارنا عن حالتها وسلوكها) وهذا الوصف هو الفئة . عندما نقوم بإنشاء كائن من فئة معينة، فإننا نحدد هذه الفئة وهذا ما يسمى " نوع الكائن ". ومن ثم يقال أن Java هي لغة مكتوبة بقوة، كما هو مذكور في مواصفات لغة Java في القسم " الفصل الرابع. الأنواع والقيم والمتغيرات ". تتبع لغة Java مفاهيم OOP وتدعم الوراثة باستخدام الكلمة الأساسية الممتدة. لماذا التوسع؟ لأنه مع الميراث، يرث الفصل الفرعي سلوك وحالة الفصل الأصلي ويمكن أن يكملهما، أي. توسيع وظائف الفئة الأساسية. يمكن أيضًا تحديد واجهة في وصف الفصل باستخدام الكلمة الأساسية للأدوات. عندما يقوم الفصل بتنفيذ واجهة، فهذا يعني أن الفصل يتوافق مع بعض العقود - إعلان من المبرمج لبقية البيئة بأن الفصل لديه سلوك معين. على سبيل المثال، لدى اللاعب أزرار مختلفة. هذه الأزرار هي واجهة للتحكم في سلوك المشغل، وسيؤدي السلوك إلى تغيير الحالة الداخلية للمشغل (على سبيل المثال، مستوى الصوت). في هذه الحالة، ستعطي الحالة والسلوك كوصف فئة. إذا قامت إحدى الفئات بتطبيق واجهة، فيمكن وصف الكائن الذي تم إنشاؤه بواسطة هذه الفئة بنوع ليس فقط من خلال الفئة، ولكن أيضًا من خلال الواجهة. لنلقي نظرة على مثال:
public class MusicPlayer {

    public static interface Device {
        public void turnOn();
        public void turnOff();
    }

    public static class Mp3Player implements Device {
        public void turnOn() {
            System.out.println("On. Ready for mp3.");
        }
        public void turnOff() {
            System.out.println("Off");
        }
    }

    public static class Mp4Player extends Mp3Player {
        @Override
        public void turnOn() {
            System.out.println("On. Ready for mp3/mp4.");
        }
    }

    public static void main(String []args) throws Exception{
        // Какое-то устройство (Тип = Device)
        Device mp3Player = new Mp3Player();
        mp3Player.turnOn();
        // У нас есть mp4 проигрыватель, но нам от него нужно только mp3
        // Пользуемся им How mp3 проигрывателем (Тип = Mp3Player)
        Mp3Player mp4Player = new Mp4Player();
        mp4Player.turnOn();
    }
}
النوع هو وصف مهم جدا. فهو يخبرنا كيف سنعمل مع الشيء، أي. ما السلوك الذي نتوقعه من الكائن. السلوكيات هي أساليب. لذلك، دعونا نفهم الأساليب. في موقع Oracle الإلكتروني، تحتوي الأساليب على قسم خاص بها في برنامج Oracle التعليمي: " تعريف الأساليب ". أول شيء يجب استخلاصه من المقالة: توقيع الطريقة هو اسم الطريقة وأنواع المعلمات :
تعدد الأشكال وأصدقائه - 2
على سبيل المثال، عند الإعلان عن طريقة عامة باطلة (Object o)، سيكون التوقيع هو اسم الطريقة ونوع المعلمة Object. لم يتم تضمين نوع الإرجاع في التوقيع. انه مهم! بعد ذلك، دعونا نجمع كود المصدر الخاص بنا. كما نعلم، لهذا يجب حفظ الكود في ملف باسم الفئة والملحق java. يتم تجميع تعليمات Java البرمجية باستخدام برنامج التحويل البرمجي " javac " إلى بعض التنسيقات المتوسطة التي يمكن تنفيذها بواسطة Java Virtual Machine (JVM). يُطلق على هذا التنسيق الوسيط اسم bytecode وهو موجود في ملفات ذات ملحق .class. لنقم بتشغيل أمر التجميع: javac MusicPlayer.java بعد تجميع كود جافا، يمكننا تنفيذه. باستخدام الأداة المساعدة " java " للبدء، سيتم تشغيل عملية آلة Java الافتراضية لتنفيذ الكود الثانوي الذي تم تمريره في ملف الفئة. لنقم بتشغيل الأمر لتشغيل التطبيق: java MusicPlayer. سنرى على الشاشة النص المحدد في معلمة الإدخال الخاصة بطريقة println. ومن المثير للاهتمام، أنه بوجود الرمز الثانوي في ملف بامتداد .class، يمكننا مشاهدته باستخدام الأداة المساعدة " javap ". لنقم بتشغيل الأمر <ocde>javap -c MusicPlayer:
تعدد الأشكال وأصدقائه - 3
من الكود الثانوي يمكننا أن نرى أن استدعاء الطريقة من خلال كائن تم تحديد نوعه يتم باستخدامه invokevirtual، وقد قام المترجم بحساب توقيع الطريقة الذي يجب استخدامه. لماذا invokevirtual؟ نظرًا لوجود استدعاء (يتم ترجمة الاستدعاء على أنه اتصال) للطريقة الافتراضية. ما هي الطريقة الافتراضية؟ هذه هي الطريقة التي يمكن تجاوز جسمها أثناء تنفيذ البرنامج. تخيل ببساطة أن لديك قائمة من المراسلات بين مفتاح معين (توقيع الطريقة) ونص (رمز) الطريقة. وقد تتغير هذه المراسلات بين المفتاح ونص الطريقة أثناء تنفيذ البرنامج. ولذلك فإن الطريقة افتراضية. افتراضيًا، في Java، تكون الطرق غير الثابتة وغير النهائية وغير الخاصة افتراضية. بفضل هذا، تدعم Java مبدأ البرمجة الشيئية المتمثل في تعدد الأشكال. كما كنت قد فهمت بالفعل، هذا هو ما تدور حوله مراجعتنا اليوم.

تعدد الأشكال

يوجد على موقع Oracle الإلكتروني في البرنامج التعليمي الرسمي قسم منفصل: " تعدد الأشكال ". دعونا نستخدم Java Online Compiler لنرى كيف يعمل تعدد الأشكال في Java. على سبيل المثال، لدينا بعض أرقام الفئة المجردة التي تمثل رقمًا في Java. ماذا يسمح؟ لديه بعض التقنيات الأساسية التي سيمتلكها جميع الورثة. أي شخص يرث من Number يقول حرفيًا - "أنا رقم، يمكنك العمل معي كرقم". على سبيل المثال، لأي لاحقة يمكنك استخدام طريقة intValue() للحصول على قيمة العدد الصحيح الخاص بها. إذا نظرت إلى Java API للرقم، يمكنك أن ترى أن الطريقة مجردة، أي أن كل خليفة للرقم يجب أن ينفذ هذه الطريقة بنفسه. ولكن ماذا يعطينا هذا؟ لنلقي نظرة على مثال:
public class HelloWorld {

    public static int summ(Number first, Number second) {
        return first.intValue() + second.intValue();
    }

    public static void main(String []args){
        System.out.println(summ(1, 2));
        System.out.println(summ(1L, 4L));
        System.out.println(summ(1L, 5));
        System.out.println(summ(1.0, 3));
    }
}
كما يتبين من المثال، بفضل تعدد الأشكال، يمكننا كتابة طريقة تقبل الوسائط من أي نوع كمدخلات، والتي ستكون سليل الرقم (لا يمكننا الحصول على الرقم، لأنه فئة مجردة). كما كان الحال مع مثال اللاعب، في هذه الحالة نقول أننا نريد العمل مع شيء ما، مثل Number. نحن نعلم أن أي شخص يكون رقمًا يجب أن يكون قادرًا على تقديم قيمته الصحيحة. وهذا يكفي بالنسبة لنا. لا نريد الخوض في تفاصيل تنفيذ كائن معين ونريد العمل مع هذا الكائن من خلال طرق مشتركة بين جميع أحفاد Number. سيتم تحديد قائمة الأساليب التي ستكون متاحة لنا حسب النوع في وقت الترجمة (كما رأينا سابقًا في الكود الثانوي). في هذه الحالة، سيكون نوعنا هو الرقم. كما ترون من المثال، فإننا نقوم بتمرير أرقام مختلفة من أنواع مختلفة، أي أن الطريقة summ ستتلقى عددًا صحيحًا وطويلًا ومزدوجًا كمدخلات. ولكن القاسم المشترك بينهم جميعًا هو أنهم من نسل الرقم المجرد، وبالتالي يتجاوزون سلوكهم في طريقة intValue، لأن يعرف كل نوع محدد كيفية إرسال هذا النوع إلى عدد صحيح. يتم تنفيذ تعدد الأشكال هذا من خلال ما يسمى بالتجاوز في اللغة الإنجليزية.
تعدد الأشكال وأصدقائه - 4
تعدد الأشكال الغالب أو الديناميكي. لذا، فلنبدأ بحفظ ملف HelloWorld.java بالمحتوى التالي:
public class HelloWorld {
    public static class Parent {
        public void method() {
            System.out.println("Parent");
        }
    }
    public static class Child extends Parent {
        public void method() {
            System.out.println("Child");
        }
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();
        parent.method();
        child.method();
    }
}
فلنفعل javac HelloWorld.javaو javap -c HelloWorld:
تعدد الأشكال وأصدقائه - 5
كما ترون، في الكود الثانوي للأسطر التي تحتوي على استدعاء الأسلوب، تتم الإشارة إلى نفس المرجع إلى أسلوب الاتصال invokevirtual (#6). دعنا نقوم به java HelloWorld. كما نرى، يتم الإعلان عن المتغيرين الأصل والطفل بالنوع الأصل، ولكن يتم استدعاء التنفيذ نفسه وفقًا للكائن الذي تم تعيينه للمتغير (أي نوع الكائن). أثناء تنفيذ البرنامج (يقال أيضًا في وقت التشغيل)، يقوم JVM، اعتمادًا على الكائن، عند استدعاء الأساليب باستخدام نفس التوقيع، بتنفيذ طرق مختلفة. وهذا يعني أنه باستخدام مفتاح التوقيع المقابل، تلقينا أولاً نص طريقة واحدًا، ثم تلقينا نصًا آخر. اعتمادا على الكائن الموجود في المتغير. ويسمى هذا التحديد في وقت تنفيذ البرنامج للطريقة التي سيتم استدعاؤها أيضًا بالربط المتأخر أو الربط الديناميكي. أي أن المطابقة بين التوقيع ونص الطريقة يتم إجراؤها ديناميكيًا، اعتمادًا على الكائن الذي يتم استدعاء الطريقة عليه. وبطبيعة الحال، لا يمكنك تجاوز الأعضاء الثابتين في الفصل (عضو الفصل)، وكذلك أعضاء الفصل الذين لديهم نوع الوصول خاص أو نهائي. تأتي التعليقات التوضيحيةOverride أيضًا لمساعدة المطورين. إنه يساعد المترجم على فهم أننا في هذه المرحلة سنقوم بتجاوز سلوك طريقة السلف. إذا ارتكبنا خطأ في توقيع الطريقة، فسيخبرنا المترجم بذلك على الفور. على سبيل المثال:
public static class Parent {
        public void method() {
            System.out.println("parent");
        }
}
public static class Child extends Parent {
        @Override
        public void method(String text) {
            System.out.println("child");
        }
}
لا يتم التجميع مع الخطأ: الخطأ: الطريقة لا تتجاوز أو تنفذ طريقة من النوع الفائق
تعدد الأشكال وأصدقائه - 6
ترتبط إعادة التعريف أيضًا بمفهوم " التباين ". لنلقي نظرة على مثال:
public class HelloWorld {
    public static class Parent {
        public Number method() {
            return 1;
        }
    }
    public static class Child extends Parent {
        @Override
        public Integer method() {
            return 2;
        }
    }

    public static void main(String[] args) {
        System.out.println(new Child().method());
    }
}
على الرغم من الغموض الواضح، فإن المعنى يتلخص في حقيقة أنه عند التجاوز، يمكننا إرجاع ليس فقط النوع الذي تم تحديده في السلف، ولكن أيضًا نوع أكثر تحديدًا. على سبيل المثال، أعاد الجد الرقم، ويمكننا إرجاع عدد صحيح - سليل الرقم. الأمر نفسه ينطبق على الاستثناءات المعلنة في رميات الطريقة. يمكن للورثة تجاوز الطريقة وتحسين الاستثناء المطروح. لكنهم لا يستطيعون التوسع. أي أنه إذا قام الوالد بطرح IOException، فيمكننا رمي EOFException الأكثر دقة، لكن لا يمكننا طرح استثناء. وبالمثل، لا يمكنك تضييق النطاق ولا يمكنك فرض قيود إضافية. على سبيل المثال، لا يمكنك إضافة ثابت.
تعدد الأشكال وأصدقائه - 7

إخفاء

هناك أيضًا شيء مثل " الإخفاء ". مثال:
public class HelloWorld {
    public static class Parent {
        public static void method() {
            System.out.println("Parent");
        }
    }
    public static class Child extends Parent {
        public static void method() {
            System.out.println("Child");
        }
    }

    public static void main(String[] args) {
        Parent parent = new Parent();
        Parent child = new Child();
        parent.method();
        child.method();
    }
}
هذا شيء واضح جدًا إذا فكرت فيه. الأعضاء الثابتون في الفصل ينتمون إلى الفصل، أي. لنوع المتغير . لذلك، فمن المنطقي أنه إذا كان الطفل من النوع الأصل، فسيتم استدعاء الطريقة على الأصل، وليس على الطفل. إذا نظرنا إلى الكود الثانوي، كما فعلنا سابقًا، فسنرى أن الطريقة الثابتة تسمى باستخدام الاستدعاء. يشرح هذا لـ JVM أنه يحتاج إلى النظر إلى النوع، وليس إلى جدول الطريقة، كما فعل inventionvirtual أو inventioninterface.
تعدد الأشكال وأصدقائه - 8

طرق التحميل الزائد

ماذا نرى أيضًا في برنامج Java Oracle التعليمي؟ في القسم الذي تمت دراسته مسبقًا " تحديد الطرق " هناك شيء يتعلق بالتحميل الزائد. ما هو؟ في اللغة الروسية، هذا هو "طريقة التحميل الزائد"، وتسمى هذه الأساليب "محملة بشكل زائد". لذلك، طريقة التحميل الزائد. للوهلة الأولى، كل شيء بسيط. دعونا نفتح مترجم جافا عبر الإنترنت، على سبيل المثال، برنامج تحويل جافا التعليمي على الإنترنت .
public class HelloWorld {

	public static void main(String []args){
		HelloWorld hw = new HelloWorld();
		hw.say(1);
		hw.say("1");
	}

	public static void say(Integer number) {
		System.out.println("Integer " + number);
	}
	public static void say(String number) {
		System.out.println("String " + number);
	}
}
لذلك، كل شيء يبدو بسيطا هنا. كما هو مذكور في برنامج Oracle التعليمي، تختلف الطرق المحملة بشكل زائد (في هذه الحالة طريقة القول) في عدد ونوع الوسائط التي تم تمريرها إلى الطريقة. لا يمكنك الإعلان عن نفس الاسم ونفس عدد الأنواع المتطابقة من الوسائط، لأن لن يتمكن المترجم من تمييزها عن بعضها البعض. تجدر الإشارة إلى شيء مهم جدًا على الفور:
تعدد الأشكال وأصدقائه - 9
وهذا هو، عند التحميل الزائد، يتحقق المترجم من الصحة. انه مهم. ولكن كيف يحدد المترجم بالفعل ضرورة استدعاء طريقة معينة؟ يستخدم قاعدة "الطريقة الأكثر تحديدًا" الموضحة في مواصفات لغة Java: " 15.12.2.5. اختيار الطريقة الأكثر تحديدًا ". لتوضيح كيفية عمله، لنأخذ مثالاً من Oracle Certified Professional Java Programmer:
public class Overload{
  public void method(Object o) {
    System.out.println("Object");
  }
  public void method(java.io.FileNotFoundException f) {
    System.out.println("FileNotFoundException");
  }
  public void method(java.io.IOException i) {
    System.out.println("IOException");
  }
  public static void main(String args[]) {
    Overload test = new Overload();
    test.method(null);
  }
}
خذ مثالاً من هنا: https://github.com/stokito/OCPJP/blob/master/src/ru/habrahabr/blogs/java/OCPJP1/question1/Overload.j... كما ترون، نحن نمر فارغة للطريقة. يحاول المترجم تحديد النوع الأكثر تحديدًا. الكائن غير مناسب لأن كل شيء موروث منه. تفضل. هناك فئتان من الاستثناءات. دعونا نلقي نظرة على java.io.IOException ونرى أن هناك FileNotFoundException في "الفئات الفرعية المعروفة المباشرة". وهذا يعني أن FileNotFoundException هو النوع الأكثر تحديدًا. لذلك، ستكون النتيجة إخراج السلسلة "FileNotFoundException". ولكن إذا استبدلنا IOException بـ EOFException، يتبين أن لدينا طريقتين على نفس مستوى التسلسل الهرمي في شجرة النوع، أي أن IOException هو الأصل لكليهما. لن يتمكن المترجم من اختيار الطريقة التي سيتم الاتصال بها وسيؤدي إلى حدوث خطأ في الترجمة: reference to method is ambiguous. مثال آخر:
public class Overload{
    public static void method(int... array) {
        System.out.println("1");
    }

    public static void main(String args[]) {
        method(1, 2);
    }
}
سيتم إخراج 1. لا توجد أسئلة هنا. النوع int... هو vararg https://docs.Oracle.com/javase/8/docs/technotes/guides/language/varargs.html وهو في الواقع ليس أكثر من "سكر نحوي" وهو في الواقع int. .. يمكن قراءة المصفوفة كصفيف int[]. إذا أضفنا الآن طريقة:
public static void method(long a, long b) {
	System.out.println("2");
}
ثم لن يتم عرض 1، بل 2، لأنه نحن نقوم بتمرير رقمين، والوسيطتان متطابقتان بشكل أفضل من صفيف واحد. إذا أضفنا طريقة:
public static void method(Integer a, Integer b) {
	System.out.println("3");
}
ثم سنظل نرى 2. لأنه في هذه الحالة تكون البدائيات أكثر دقة من الملاكمة في عدد صحيح. ومع ذلك، إذا نفذنا، method(new Integer(1), new Integer(2));فسيتم طباعة 3. تشبه المنشئات في Java الأساليب، وبما أنه يمكن استخدامها أيضًا للحصول على توقيع، تنطبق عليها نفس قواعد "حل التحميل الزائد" كطرق محملة بشكل زائد. تخبرنا مواصفات لغة Java بذلك في " 8.8.8. التحميل الزائد للمنشئ ". التحميل الزائد للطريقة = الربط المبكر (المعروف أيضًا باسم الربط الثابت) يمكنك غالبًا أن تسمع عن الربط المبكر والمتأخر، المعروف أيضًا باسم الربط الثابت أو الربط الديناميكي. الفرق بينهما بسيط جدا. مبكرًا هو التجميع، متأخرًا هي لحظة تنفيذ البرنامج. لذلك، فإن الربط المبكر (الربط الثابت) هو تحديد الطريقة التي سيتم استدعاؤها لمن في وقت الترجمة. حسنًا، الربط المتأخر (الربط الديناميكي) هو تحديد الطريقة التي سيتم الاتصال بها مباشرة في وقت تنفيذ البرنامج. كما رأينا سابقًا (عندما قمنا بتغيير IOException إلى EOFException)، إذا قمنا بتحميل الأساليب بشكل زائد بحيث لا يتمكن المترجم من فهم مكان إجراء أي استدعاء، فسنحصل على خطأ في وقت الترجمة: الإشارة إلى الطريقة غامضة. كلمة غامضة مترجمة من الإنجليزية تعني غامضة أو غير مؤكدة وغير دقيقة. اتضح أن التحميل الزائد ملزم مبكرًا، لأن يتم إجراء الفحص في وقت الترجمة. لتأكيد استنتاجاتنا، دعونا نفتح مواصفات لغة جافا في الفصل " 8.4.9. التحميل الزائد ":
تعدد الأشكال وأصدقائه - 10
اتضح أنه أثناء الترجمة، سيتم استخدام معلومات حول أنواع وعدد الوسائط (المتوفرة في وقت الترجمة) لتحديد توقيع الطريقة. إذا كانت الطريقة إحدى طرق الكائن (أي طريقة المثيل)، فسيتم تحديد استدعاء الطريقة الفعلي في وقت التشغيل باستخدام البحث عن الطريقة الديناميكية (أي الربط الديناميكي). ولتوضيح الأمر أكثر، لنأخذ مثالًا مشابهًا للمثال الذي ناقشناه سابقًا:
public class HelloWorld {
    public void method(int intNumber) {
        System.out.println("intNumber");
    }
    public void method(Integer intNumber) {
        System.out.println("Integer");
    }
    public void method(String intNumber) {
        System.out.println("Number is: " + intNumber);
    }

    public static void main(String args[]) {
        HelloWorld test = new HelloWorld();
        test.method(2);
    }
}
لنحفظ هذا الرمز في ملف HelloWorld.java ونقوم بتجميعه باستخدام javac HelloWorld.java الآن، لنرى ما كتبه مترجمنا في الكود الثانوي عن طريق تشغيل الأمر: javap -verbose HelloWorld.
تعدد الأشكال وأصدقائه - 11
كما ذكرنا، قرر المترجم أنه سيتم استدعاء بعض الطرق الافتراضية في المستقبل. أي أنه سيتم تعريف نص الطريقة في وقت التشغيل. لكن في وقت التجميع، من بين الطرق الثلاث، اختار المترجم الطريقة الأكثر ملاءمة، لذلك أشار إلى الرقم:"invokevirtual #13"
تعدد الأشكال وأصدقائه - 12
أي نوع من المنهجية هذا؟ وهذا رابط للطريقة . بشكل تقريبي، هذا هو بعض الأدلة التي يمكن لـ Java Virtual Machine من خلالها، في وقت التشغيل، تحديد الطريقة التي يجب البحث عنها للتنفيذ. يمكن العثور على مزيد من التفاصيل في المقالة الرائعة: " كيف يتعامل JVM مع التحميل الزائد للطريقة والتجاوز داخليًا ".

تلخيص

لذلك، اكتشفنا أن Java، باعتبارها لغة موجهة للكائنات، تدعم تعدد الأشكال. يمكن أن يكون تعدد الأشكال ثابتًا (الربط الثابت) أو ديناميكيًا (الربط الديناميكي). مع تعدد الأشكال الثابت، المعروف أيضًا باسم الربط المبكر، يحدد المترجم الطريقة التي يجب استدعاؤها وأين. وهذا يسمح باستخدام آلية مثل التحميل الزائد. مع تعدد الأشكال الديناميكي، المعروف أيضًا باسم الارتباط المتأخر، استنادًا إلى التوقيع المحسوب مسبقًا للطريقة، سيتم حساب الطريقة في وقت التشغيل بناءً على الكائن المستخدم (أي طريقة الكائن التي يتم استدعاؤها). يمكن رؤية كيفية عمل هذه الآليات باستخدام الرمز الثانوي. ينظر التحميل الزائد إلى توقيعات الطريقة، وعند حل التحميل الزائد، يتم اختيار الخيار الأكثر تحديدًا (الأكثر دقة). ينظر التجاوز إلى النوع لتحديد الأساليب المتاحة، ويتم استدعاء الأساليب نفسها بناءً على الكائن. وكذلك المواد المتعلقة بالموضوع: # فياتشيسلاف
تعليقات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION