JavaRush /وبلاگ جاوا /Random-FA /چند شکلی و دوستان آن
Viacheslav
مرحله

چند شکلی و دوستان آن

در گروه منتشر شد
چندشکلی یکی از اصول اساسی برنامه نویسی شی گرا است. این به شما امکان می دهد تا از قدرت تایپ قوی جاوا استفاده کنید و کدهای قابل استفاده و نگهداری بنویسید. چیزهای زیادی در مورد او گفته شده است، اما امیدوارم همه بتوانند چیز جدیدی را از این بررسی حذف کنند.
چند شکلی و دوستان آن - 1

معرفی

فکر می کنم همه ما می دانیم که زبان برنامه نویسی جاوا متعلق به اوراکل است. بنابراین، مسیر ما با سایت: www.oracle.com آغاز می شود . یک "منو" در صفحه اصلی وجود دارد. در آن، در بخش "اسناد" یک زیربخش "جاوا" وجود دارد. هر چیزی که به توابع اصلی زبان مربوط می شود متعلق به "مستندات جاوا SE" است، بنابراین ما این بخش را انتخاب می کنیم. بخش مستندات برای آخرین نسخه باز می شود، اما در حال حاضر "در جستجوی نسخه ای متفاوت هستید؟" بیایید گزینه را انتخاب کنیم: JDK8. در صفحه گزینه های مختلفی را مشاهده خواهیم کرد. اما ما به یادگیری زبان علاقه مندیم: " مسیرهای یادگیری آموزش جاوا ". در این صفحه ما بخش دیگری را پیدا خواهیم کرد: " آموزش زبان جاوا ". این مقدس ترین مقدس است، آموزش اصول اولیه جاوا از Oracle. جاوا یک زبان برنامه نویسی شی گرا (OOP) است، بنابراین یادگیری این زبان حتی در وب سایت اوراکل با بحث در مورد مفاهیم اولیه " مفاهیم برنامه نویسی شی گرا " آغاز می شود. از خود نام مشخص است که جاوا بر روی کار با اشیاء متمرکز شده است. از زیر بخش " یک شی چیست؟ " مشخص می شود که اشیاء در جاوا از حالت و رفتار تشکیل شده اند. تصور کنید که ما یک حساب بانکی داریم. مقدار پول در حساب حالت است و روش های کار با این حالت رفتاری است. اشیا باید به نحوی توصیف شوند (بگویید چه حالت و رفتاری ممکن است داشته باشند) و این توصیف کلاس است . هنگامی که یک شی از یک کلاس ایجاد می کنیم، این کلاس را مشخص می کنیم و به آن " نوع شی " می گویند. از این رو گفته می شود که جاوا یک زبان با تایپ قوی است، همانطور که در مشخصات زبان جاوا در بخش " فصل 4. انواع، مقادیر و متغیرها " بیان شده است. زبان جاوا از مفاهیم OOP پیروی می کند و از وراثت با استفاده از کلمه کلیدی extends پشتیبانی می کند. چرا گسترش؟ زیرا با وراثت، یک کلاس فرزند رفتار و حالت کلاس والد را به ارث می برد و می تواند آنها را تکمیل کند، یعنی. گسترش عملکرد کلاس پایه یک رابط را می توان در توضیحات کلاس با استفاده از کلمه کلیدی implements نیز مشخص کرد. هنگامی که یک کلاس یک رابط را پیاده سازی می کند، به این معنی است که کلاس با برخی قراردادها مطابقت دارد - اعلامیه ای توسط برنامه نویس به بقیه محیط که کلاس رفتار خاصی دارد. به عنوان مثال، پخش کننده دکمه های مختلفی دارد. این دکمه ها رابطی برای کنترل رفتار پخش کننده هستند و رفتار باعث تغییر حالت داخلی پخش کننده (مثلاً صدا) می شود. در این حالت، حالت و رفتار به عنوان یک توصیف، یک کلاس می دهد. اگر یک کلاس یک اینترفیس را پیاده سازی کند، آنگاه یک شی ایجاد شده با استفاده از این کلاس می تواند با یک نوع نه تنها توسط کلاس، بلکه توسط رابط نیز توصیف شود. بیایید به یک مثال نگاه کنیم:
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();
    }
}
نوع توصیف بسیار مهمی است. این نشان می دهد که چگونه می خواهیم با شی کار کنیم، i.e. چه رفتاری از شیء انتظار داریم. رفتارها روش هستند. بنابراین، بیایید روش ها را درک کنیم. در وب‌سایت اوراکل، روش‌ها بخش مخصوص به خود را در آموزش اوراکل دارند: « تعریف روش‌ها ». اولین چیزی که از مقاله حذف می شود: امضای یک متد نام روش و انواع پارامترها است :
چند شکلی و دوستان آن - 2
به عنوان مثال، هنگام اعلام یک متد public void method (Object o)، امضا نام متد و نوع پارامتر Object خواهد بود. نوع برگشتی در امضا گنجانده نشده است. مهم است! بعد، بیایید کد منبع خود را کامپایل کنیم. همانطور که می دانیم برای این کار باید کد در فایلی با نام کلاس و پسوند جاوا ذخیره شود. کد جاوا با استفاده از کامپایلر " javac " در قالبی میانی که می تواند توسط ماشین مجازی جاوا (JVM) اجرا شود، کامپایل می شود. این فرمت میانی بایت کد نامیده می شود و در فایل هایی با پسوند .class موجود است. بیایید دستور کامپایل را اجرا کنیم: javac MusicPlayer.java پس از کامپایل شدن کد جاوا، می‌توانیم آن را اجرا کنیم. با استفاده از ابزار " java " برای شروع، فرآیند ماشین مجازی جاوا برای اجرای بایت کد ارسال شده در فایل کلاس راه اندازی می شود. بیایید دستور اجرای برنامه را اجرا کنیم: java MusicPlayer. متن مشخص شده در پارامتر ورودی متد println را روی صفحه مشاهده خواهیم کرد. جالب اینجاست که با داشتن بایت کد در یک فایل با پسوند .class، می توانیم آن را با استفاده از ابزار " javap " مشاهده کنیم. بیایید دستور <ocde>javap -c MusicPlayer را اجرا کنیم:
چند شکلی و دوستان آن - 3
از بایت کد می توانیم ببینیم که فراخوانی یک متد از طریق یک شی که نوع آن کلاس مشخص شده است با استفاده از انجام می شود invokevirtualو کامپایلر محاسبه کرده است که امضای کدام متد باید استفاده شود. چرا invokevirtual؟ زیرا فراخوانی (Invoke به عنوان فراخوانی ترجمه شده است) از یک متد مجازی وجود دارد. روش مجازی چیست؟ این روشی است که بدنه آن در حین اجرای برنامه قابل بازنویسی است. به سادگی تصور کنید که لیستی از مطابقت بین یک کلید خاص (امضای روش) و بدنه (کد) روش دارید. و این مطابقت بین کلید و بدنه متد ممکن است در طول اجرای برنامه تغییر کند. بنابراین روش مجازی است. به طور پیش فرض، در جاوا، روش هایی که ثابت، نهایی و خصوصی نیستند، مجازی هستند. به لطف این، جاوا از اصل برنامه نویسی شی گرا پلی مورفیسم پشتیبانی می کند. همانطور که ممکن است قبلاً متوجه شده باشید، بررسی امروز ما در مورد این موضوع است.

پلی مورفیسم

در وب سایت Oracle در آموزش رسمی آنها یک بخش جداگانه وجود دارد: " Polymorphism ". بیایید از کامپایلر آنلاین جاوا استفاده کنیم تا ببینیم چندشکلی در جاوا چگونه کار می کند. به عنوان مثال، ما یک کلاس انتزاعی Number داریم که یک عدد را در جاوا نشان می دهد. چه چیزی اجازه می دهد؟ او چند تکنیک اساسی دارد که همه وارثان خواهند داشت. هر کسی که از Number ارث می برد به معنای واقعی کلمه می گوید - "من یک عدد هستم، شما می توانید به عنوان یک عدد با من کار کنید." به عنوان مثال، برای هر جانشینی می توانید از متد intValue() برای بدست آوردن مقدار صحیح آن استفاده کنید. اگر به api جاوا برای Number نگاه کنید، می بینید که متد انتزاعی است، یعنی هر جانشین Number باید خودش این متد را پیاده سازی کند. اما این چه چیزی به ما می دهد؟ بیایید به یک مثال نگاه کنیم:
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 را بدست آوریم، زیرا یک کلاس انتزاعی است). همانطور که در مورد مثال پخش کننده وجود داشت، در این مورد می گوییم که می خواهیم با چیزی مانند Number کار کنیم. ما می دانیم که هر کسی که یک عدد است باید بتواند مقدار صحیح آن را ارائه دهد. و همین برای ما کافی است. ما نمی خواهیم وارد جزئیات پیاده سازی یک شی خاص شویم و می خواهیم از طریق روش های مشترک برای همه فرزندان Number با این شی کار کنیم. لیست روش هایی که در دسترس ما خواهد بود بر اساس نوع در زمان کامپایل تعیین می شود (همانطور که قبلا در بایت کد دیدیم). در این صورت نوع ما Number خواهد بود. همانطور که از مثال می بینید، ما در حال ارسال اعداد مختلف از انواع مختلف هستیم، یعنی متد summary عدد صحیح، طولانی و دوگانه را به عنوان ورودی دریافت می کند. اما وجه مشترک همه آنها این است که آنها از نوادگان عدد انتزاعی هستند و بنابراین رفتار خود را در روش intValue نادیده می گیرند، زیرا هر نوع خاص می داند که چگونه آن نوع را به عدد صحیح ارسال کند. چنین چندشکلی از طریق به اصطلاح overriding در انگلیسی Overriding اجرا می شود.
چند شکلی و دوستان آن - 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بیا انجامش بدیم همانطور که می بینیم، متغیرهای parent و فرزند با نوع Parent اعلان می شوند، اما خود پیاده سازی با توجه به اینکه چه شی به متغیر اختصاص داده شده است (یعنی چه نوع شی) فراخوانی می شود. در طول اجرای برنامه (در زمان اجرا هم می گویند)، JVM، بسته به شی، هنگام فراخوانی متدها با استفاده از امضای یکسان، روش های مختلفی را اجرا می کند. یعنی با استفاده از کلید امضای مربوطه، ابتدا یک متد را دریافت کردیم و سپس دیگری را دریافت کردیم. بسته به اینکه چه شی در متغیر است. این تعیین در زمان اجرای برنامه که کدام متد فراخوانی می شود را بایند دیرهنگام یا Dynamic Binding نیز می گویند. یعنی مطابقت بین امضا و بدنه متد بسته به شیئی که متد بر روی آن فراخوانی می شود به صورت پویا انجام می شود. به طور طبیعی، نمی‌توانید اعضای ثابت یک کلاس (عضو کلاس)، و همچنین اعضای کلاس با نوع دسترسی خصوصی یا نهایی را لغو کنید. حاشیه نویسی @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");
        }
}
با خطا کامپایل نمی شود: error: متد یک متد از supertype را لغو یا پیاده سازی نمی کند
چند شکلی و دوستان آن - 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());
    }
}
علیرغم ابهام ظاهری، معنا به این می رسد که در هنگام غلبه، می توانیم نه تنها نوعی را که در جد مشخص شده است، بلکه یک نوع خاص تر را نیز برگردانیم. به عنوان مثال، جد Number را برگرداند، و ما می توانیم Integer - نوادگان Number را برگردانیم. همین امر در مورد استثناهای اعلام شده در پرتاب های متد نیز صدق می کند. وارثان می توانند روش را نادیده بگیرند و استثنای پرتاب شده را اصلاح کنند. اما آنها نمی توانند گسترش یابند. یعنی اگر والد یک IOException پرتاب کند، می‌توانیم EOFException دقیق‌تر را پرتاب کنیم، اما نمی‌توانیم Exception را پرتاب کنیم. به همین ترتیب، شما نمی توانید دامنه را محدود کنید و نمی توانید محدودیت های اضافی اعمال کنید. به عنوان مثال، شما نمی توانید استاتیک را اضافه کنید.
چند شکلی و دوستان آن - 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();
    }
}
اگر در مورد آن فکر کنید این یک چیز کاملاً واضح است. اعضای ایستا یک کلاس متعلق به کلاس هستند، یعنی. به نوع متغیر بنابراین، منطقی است که اگر فرزند از نوع Parent باشد، متد روی Parent فراخوانی شود نه فرزند. اگر به بایت کد نگاه کنیم، همانطور که قبلا انجام دادیم، خواهیم دید که روش static با استفاده از invokestatic نامیده می شود. این به JVM توضیح می‌دهد که باید به نوع نگاه کند، نه به جدول متد، همانطور که invokevirtual یا invokeinterface انجام داد.
چند شکلی و دوستان آن - 8

روش های اضافه بار

چه چیز دیگری در آموزش جاوا اوراکل می بینیم؟ در بخش " تعریف روش ها " که قبلاً مورد مطالعه قرار گرفت، چیزی در مورد اضافه بار وجود دارد. آن چیست؟ در روسی این "بارگذاری بیش از حد روش" است و به این روش ها "سربارگذاری" گفته می شود. بنابراین، روش اضافه بار. در نگاه اول همه چیز ساده است. بیایید یک کامپایلر آنلاین جاوا را باز کنیم، به عنوان مثال ، کامپایلر جاوا را به آموزش اشاره کنیم .
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
یعنی هنگام بارگذاری بیش از حد، کامپایلر صحت را بررسی می کند. مهم است. اما چگونه کامپایلر در واقع تشخیص می دهد که یک متد خاص باید فراخوانی شود؟ از قانون "ویژه ترین روش" که در مشخصات زبان جاوا توضیح داده شده است استفاده می کند: " 15.12.2.5. انتخاب روش خاص ". برای نشان دادن نحوه کارکرد آن، بیایید مثالی از برنامه نویس حرفه ای جاوا با گواهی Oracle بزنیم:
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... همانطور که می بینید، ما در حال عبور هستیم تهی روش. کامپایلر سعی می کند خاص ترین نوع را تعیین کند. شی مناسب نیست زیرا همه چیز از او به ارث رسیده است. برو جلو. 2 کلاس استثنا وجود دارد. بیایید به 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 را نمایش می دهد، زیرا ما در حال ارسال 2 عدد هستیم و 2 آرگومان تطبیق بهتری نسبت به یک آرایه دارند. اگر یک روش اضافه کنیم:
public static void method(Integer a, Integer b) {
	System.out.println("3");
}
سپس ما هنوز هم 2 را خواهیم دید. زیرا در این مورد ابتدایی ها تطابق دقیق تری نسبت به بوکس در عدد صحیح دارند. با این حال، اگر اجرا کنیم، method(new Integer(1), new Integer(2));3 را چاپ می‌کند. سازنده‌ها در جاوا شبیه به متدها هستند، و از آنجایی که می‌توان از آنها برای به دست آوردن امضا نیز استفاده کرد، همان قوانین «رزلوشن اضافه بار» مانند روش‌های بارگذاری شده برای آنها اعمال می‌شود. مشخصات زبان جاوا این را در " 8.8.8. Constructor Overloading " به ما می گوید. روش بیش از حد = صحافی زودرس (معروف به استاتیک صحافی) اغلب می توانید در مورد صحافی زودهنگام و دیرهنگام بشنوید که به نام های Static Binding یا Dynamic Binding نیز شناخته می شود. تفاوت بین آنها بسیار ساده است. کامپایل زود است، زمان اجرای برنامه دیر است. بنابراین، اتصال اولیه (Static binding) تعیین این است که کدام روش در زمان کامپایل بر روی چه کسی فراخوانی خواهد شد. خوب، اتصال دیرهنگام (binding پویا) تعیین این است که در زمان اجرای برنامه، کدام متد را به طور مستقیم فراخوانی کنیم. همانطور که قبلاً دیدیم (زمانی که 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
این چه نوع متدرفی است؟ این یک لینک به روش است. به طور کلی، این سرنخ‌هایی است که در زمان اجرا، ماشین مجازی جاوا می‌تواند واقعاً تعیین کند که کدام روش را برای اجرا جستجو کند. جزئیات بیشتر را می‌توانید در مقاله فوق‌العاده پیدا کنید: " چگونه JVM با بارگذاری و نادیده گرفتن داخلی روش مدیریت می‌کند ".

خلاصه کردن

بنابراین، متوجه شدیم که جاوا، به عنوان یک زبان شی گرا، از چند شکلی پشتیبانی می کند. پلی مورفیسم می تواند ایستا (Static Binding) یا دینامیک (Dynamic Binding) باشد. با پلی مورفیسم ایستا، که به عنوان اتصال اولیه نیز شناخته می شود، کامپایلر تعیین می کند که کدام روش و کجا باید فراخوانی شود. این امکان استفاده از مکانیزمی مانند اضافه بار را فراهم می کند. با پلی مورفیسم پویا، که به عنوان اتصال دیرهنگام نیز شناخته می شود، بر اساس امضای محاسبه شده قبلی یک روش، یک روش در زمان اجرا بر اساس شی مورد استفاده محاسبه می شود (به عنوان مثال، روش شیء نامیده می شود). نحوه کار این مکانیسم ها را می توان با استفاده از بایت کد مشاهده کرد. اضافه بار به امضاهای روش نگاه می کند و هنگام حل اضافه بار، خاص ترین (دقیق ترین) گزینه انتخاب می شود. Overriding به نوع نگاه می کند تا مشخص کند چه روش هایی در دسترس هستند و خود متدها بر اساس شی نامیده می شوند. و همچنین مطالبی در مورد موضوع: #ویاچسلاو
نظرات
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION