JavaRush /Java Blogu /Random-AZ /Polimorfizm və onun dostları
Viacheslav
Səviyyə

Polimorfizm və onun dostları

Qrupda dərc edilmişdir
Polimorfizm obyekt yönümlü proqramlaşdırmanın əsas prinsiplərindən biridir. O, sizə Java-nın güclü yazma gücündən istifadə etməyə və istifadə edilə bilən və saxlanıla bilən kodu yazmağa imkan verir. Onun haqqında çox şey deyildi, amma ümid edirəm ki, hər kəs bu baxışdan yeni bir şey götürə bilər.
Polimorfizm və onun dostları - 1

Giriş

Düşünürəm ki, Java proqramlaşdırma dilinin Oracle-a aid olduğunu hamımız bilirik. Buna görə də yolumuz saytdan başlayır: www.oracle.com . Əsas səhifədə "Menyu" var. Orada "Sənədlər" bölməsində "Java" alt bölməsi var. Dilin əsas funksiyalarına aid olan hər şey "Java SE sənədləri"nə aiddir, ona görə də bu bölməni seçirik. Sənədlər bölməsi ən son versiya üçün açılacaq, lakin hələlik "Fərqli buraxılış axtarırsınız?" Seçimi seçək: JDK8. Səhifədə çoxlu müxtəlif variantları görəcəyik. Lakin biz Dil Öyrənməklə maraqlanırıq: " Java Dərslikləri Öyrənmə Yolları ". Bu səhifədə başqa bir bölmə tapacağıq: " Java dilini öyrənmək ". Bu müqəddəslərin ən müqəddəsidir, Oracle-dan Java əsaslarına dair dərslikdir. Java obyekt yönümlü proqramlaşdırma dilidir (OOP), ona görə də dili hətta Oracle veb-saytında öyrənmək “ Obyekt yönümlü Proqramlaşdırma Konseptləri ” nin əsas anlayışlarının müzakirəsi ilə başlayır . Adının özündən aydın olur ki, Java obyektlərlə işləməyə yönəlib. “ Obyekt nədir? ” alt bölməsindən aydın olur ki, Java-da obyektlər vəziyyət və davranışdan ibarətdir. Təsəvvür edin ki, bizim bank hesabımız var. Hesabdakı pulun miqdarı dövlətdir və bu dövlətlə işləmə üsulları davranışdır. Obyektləri bir şəkildə təsvir etmək lazımdır (onların hansı vəziyyətə və davranışa malik ola biləcəyini söyləyin) və bu təsvir sinifdir . Hər hansı bir sinif obyekti yaratdıqda, biz bu sinfi təyin edirik və bu " obyekt növü " adlanır. Beləliklə, Java dilinin " Fəsil 4. Növlər, Dəyərlər və Dəyişənlər " bölməsindəki Java dilinin spesifikasiyasında qeyd edildiyi kimi, güclü tipli bir dil olduğu deyilir . Java dili OOP konsepsiyalarını izləyir və genişləndirir açar sözündən istifadə edərək varisliyi dəstəkləyir. Niyə genişlənmə? Çünki irsiyyətlə uşaq sinfi valideyn sinfinin davranışını və vəziyyətini miras alır və onları tamamlaya bilər, yəni. baza sinfinin funksionallığını genişləndirmək. İnterfeys sinif təsvirində tətbiq açar sözündən istifadə etməklə də göstərilə bilər. Sinif interfeysi həyata keçirdikdə, bu o deməkdir ki, sinif hansısa müqaviləyə uyğundur - proqramçının ətraf mühitin qalan hissəsinə sinfin müəyyən davranışa malik olduğunu bəyan etməsi. Məsələn, oyunçunun müxtəlif düymələri var. Bu düymələr oyunçunun davranışına nəzarət etmək üçün interfeysdir və davranış oyunçunun daxili vəziyyətini (məsələn, səs səviyyəsini) dəyişdirəcəkdir. Bu vəziyyətdə vəziyyət və davranış bir sinif olaraq bir təsvir verəcəkdir. Əgər sinif interfeysi həyata keçirirsə, o zaman bu sinif tərəfindən yaradılmış obyekt yalnız sinif tərəfindən deyil, həm də interfeys tərəfindən tiplə təsvir edilə bilər. Bir misala baxaq:
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();
    }
}
Tip çox vacib bir təsvirdir. Obyektlə necə işləyəcəyimizi bildirir, yəni. obyektdən hansı davranışı gözlədiyimizi. Davranışlar üsullardır. Buna görə də üsulları anlayaq. Oracle veb saytında metodların Oracle Təlimində öz bölməsi var: " Metodların müəyyən edilməsi ". Məqalədən götürüləcək ilk şey: Metod imzası metodun adı və parametrlərin növləridir :
Polimorfizm və onun dostları - 2
Məsələn, metodu ictimai etibarsızlıq metodu (Object o) elan edərkən, imza metodun adı və Obyekt parametrinin növü olacaqdır. Qaytarma növü imzaya daxil DEYİL. Vacibdir! Sonra mənbə kodumuzu tərtib edək. Bildiyimiz kimi, bunun üçün kod sinifin adı və java uzantısı olan faylda saxlanmalıdır. Java kodu " javac " kompilyatorundan istifadə edərək Java Virtual Maşın (JVM) tərəfindən icra oluna bilən bəzi ara formatda tərtib edilir. Bu aralıq format bayt kodu adlanır və .class uzantılı fayllarda olur. Kompilyasiya əmrini yerinə yetirək: javac MusicPlayer.java Java kodu tərtib edildikdən sonra onu icra edə bilərik. Başlamaq üçün " java " yardım proqramından istifadə edərək, sinif faylında ötürülən bayt kodunu yerinə yetirmək üçün Java virtual maşın prosesi işə salınacaq. Proqramı işə salmaq üçün əmri yerinə yetirək: java MusicPlayer. Biz ekranda println metodunun daxiletmə parametrində göstərilən mətni görəcəyik. Maraqlıdır ki, bayt kodu .class uzantılı faylda olduğu üçün biz ona " javap " yardım proqramından istifadə edərək baxa bilərik. <ocde>javap -c MusicPlayer əmrini yerinə yetirək:
Polimorfizm və onun dostları - 3
Bayt kodundan görə bilərik ki, növü sinfi müəyyən edilmiş obyekt vasitəsilə metodun çağırılması , istifadə edərək həyata keçirilir invokevirtualvə kompilyator hansı metod imzasının istifadə edilməli olduğunu hesablayıb. Niyə invokevirtual? Çünki virtual metodun çağırışı (invoke çağırış kimi tərcümə olunur) var. Virtual üsul nədir? Bu, proqramın icrası zamanı bədəni ləğv edilə bilən bir üsuldur. Sadəcə olaraq təsəvvür edin ki, müəyyən bir açar (metod imzası) ilə metodun gövdəsi (kodu) arasında yazışmaların siyahısı var. Və metodun açarı ilə gövdəsi arasındakı bu uyğunluq proqramın icrası zamanı dəyişə bilər. Buna görə də üsul virtualdır. Varsayılan olaraq, Java-da statik OLMAYAN, SON DEYİL və şəxsi DEYİL metodlar virtualdır. Bunun sayəsində Java polimorfizmin obyekt yönümlü proqramlaşdırma prinsipini dəstəkləyir. Artıq başa düşdüyünüz kimi, bugünkü baxışımız budur.

Polimorfizm

Oracle saytında onların rəsmi Dərsliklərində ayrıca bölmə var: " Polimorfizm ". Polimorfizmin Java-da necə işlədiyini görmək üçün Java Onlayn Kompilyatorundan istifadə edək . Məsələn, Java-da rəqəmi təmsil edən bəzi mücərrəd sinif nömrəmiz var. Nəyə icazə verir? Onun bütün varislərin sahib olacağı bəzi əsas texnikaları var. Nömrədən miras qalan hər kəs sözün əsl mənasında deyir: "Mən bir nömrəyəm, mənimlə nömrə kimi işləyə bilərsiniz." Məsələn, hər hansı bir varisin tam dəyərini almaq üçün intValue() metodundan istifadə edə bilərsiniz. Nömrə üçün java api-yə baxsanız, metodun abstrakt olduğunu görə bilərsiniz, yəni Nömrənin hər bir varisi bu metodu özü həyata keçirməlidir. Bəs bu bizə nə verir? Bir misala baxaq:
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));
    }
}
Nümunədən göründüyü kimi, polimorfizm sayəsində Nömrənin nəslindən olacaq istənilən növ arqumentləri giriş kimi qəbul edəcək bir üsul yaza bilərik (abstrakt sinif olduğu üçün Number ala bilmirik). Oyunçu nümunəsində olduğu kimi, bu halda biz Nömrə kimi bir şeylə işləmək istədiyimizi deyirik. Biz bilirik ki, Nömrə olan hər kəs onun tam dəyərini təmin edə bilməlidir. Və bu bizim üçün kifayətdir. Biz konkret bir obyektin həyata keçirilməsinin təfərrüatlarına girmək istəmirik və bu obyektlə Nömrənin bütün nəsilləri üçün ümumi olan üsullarla işləmək istəyirik. Bizim üçün əlçatan olacaq metodların siyahısı tərtib zamanı növə görə müəyyən ediləcək (əvvəl bayt kodunda gördüyümüz kimi). Bu halda növümüz Nömrə olacaq. Nümunədən göründüyü kimi, biz müxtəlif tipli müxtəlif nömrələri ötürürük, yəni cəm metodu Integer, Long və Double-ı giriş kimi alacaq. Lakin onların hamısının ortaq cəhəti odur ki, onlar mücərrəd Nömrənin nəslindəndirlər və buna görə də intValue metodunda öz davranışlarını ləğv edirlər, çünki hər bir xüsusi növ bu növü Tam ədədə necə köçürməyi bilir. Bu cür polimorfizm ingilis dilində Overriding deyilən üsulla həyata keçirilir.
Polimorfizm və onun dostları - 4
Qeyri-adi və ya dinamik polimorfizm. Beləliklə, HelloWorld.java faylını aşağıdakı məzmunda saxlamaqla başlayaq:
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();
    }
}
edək javac HelloWorld.javajavap -c HelloWorld:
Polimorfizm və onun dostları - 5
Gördüyünüz kimi, metod çağırışı olan sətirlərin bayt kodunda çağırış metoduna eyni istinad göstərilir invokevirtual (#6). Gəl edək java HelloWorld. Gördüyümüz kimi, valideyn və uşaq dəyişənləri Parent növü ilə elan edilir, lakin icranın özü dəyişənə hansı obyektin təyin edilməsinə (yəni, hansı obyekt növünə) görə çağırılır. Proqramın icrası zamanı (iş zamanı da deyirlər) JVM obyektdən asılı olaraq eyni imzadan istifadə edən metodları çağırarkən müxtəlif üsulları icra edirdi. Yəni, müvafiq imzanın açarından istifadə edərək əvvəlcə bir metod gövdəsini aldıq, sonra isə digərini aldıq. Dəyişəndə ​​hansı obyektin olmasından asılı olaraq. Proqramın icrası zamanı hansı metodun çağırılacağının müəyyən edilməsinə gec bağlama və ya dinamik bağlama da deyilir. Yəni, imza ilə metod gövdəsi arasında uyğunluq metodun çağırıldığı obyektdən asılı olaraq dinamik şəkildə həyata keçirilir. Təbii ki, siz sinfin statik üzvlərini (Sinif üzvü), eləcə də giriş növü özəl və ya yekun olan sinif üzvlərini ləğv edə bilməzsiniz. @Override annotasiyaları da tərtibatçıların köməyinə gəlir. Bu, tərtibçiyə başa düşməyə kömək edir ki, bu nöqtədə biz əcdad metodunun davranışını ləğv edəcəyik. Metod imzasında səhv etmişiksə, kompilyator dərhal bu barədə bizə məlumat verəcəkdir. Misal üçün:
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");
        }
}
Səhv ilə tərtib edilmir: xəta: metod supertipdən olan metodu ləğv etmir və ya həyata keçirmir
Polimorfizm və onun dostları - 6
Yenidən tərif həm də “ kovariasiya ” anlayışı ilə əlaqələndirilir . Bir misala baxaq:
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());
    }
}
Görünən mücərrədliyə baxmayaraq, məna ondan ibarətdir ki, üstəlik, biz yalnız əcdadda göstərilən növü deyil, həm də daha spesifik bir növü qaytara bilərik. Məsələn, əcdad Nömrəni qaytardı və biz Tam ədədi - Nömrənin nəslini qaytara bilərik. Eyni şey metodun atışlarında elan edilən istisnalara da aiddir. Varislər metodu ləğv edə və atılan istisnanı dəqiqləşdirə bilər. Amma genişləyə bilmirlər. Yəni, valideyn IOException atırsa, biz daha dəqiq EOFException ata bilərik, lakin İstisna ata bilmərik. Eynilə, siz əhatə dairəsini daralda və əlavə məhdudiyyətlər qoya bilməzsiniz. Məsələn, statik əlavə edə bilməzsiniz.
Polimorfizm və onun dostları - 7

Gizlətmək

“ Gizlətmək ” kimi bir şey də var . Misal:
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();
    }
}
Bu barədə düşünsəniz, bu olduqca açıq bir şeydir. Bir sinfin statik üzvləri sinfə aiddir, yəni. dəyişənin növünə görə. Ona görə də məntiqlidir ki, əgər uşaq valideyn tiplidirsə, o zaman metod uşaqda deyil, valideyndə çağırılacaq. Baytkoda nəzər salsaq, əvvəllər etdiyimiz kimi, statik metodun invokestatic istifadə edərək çağırıldığını görərik. Bu, JVM-ə izah edir ki, o, invokevirtual və ya invokeinterface kimi metod cədvəlinə deyil, tipə baxmalıdır.
Polimorfizm və onun dostları - 8

Həddindən artıq yükləmə üsulları

Java Oracle Təlimində başqa nə görürük? Əvvəllər öyrənilmiş " Metodların müəyyən edilməsi " bölməsində Həddindən artıq yükləmə haqqında bir şey var. Bu nədir? Rus dilində bu “metod overloading” və belə üsullara “overloaded” deyilir. Beləliklə, metodun həddindən artıq yüklənməsi. İlk baxışdan hər şey sadədir. Onlayn Java kompilyatorunu açaq, məsələn tutorialspoint online java compiler .
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);
	}
}
Beləliklə, burada hər şey sadə görünür. Oracle təlimatında deyildiyi kimi, həddən artıq yüklənmiş metodlar (bu halda demək metodu) metoda ötürülən arqumentlərin sayı və növü ilə fərqlənir. Siz eyni adı və eyni sayda arqument növlərini elan edə bilməzsiniz, çünki kompilyator onları bir-birindən ayıra bilməyəcək. Dərhal çox vacib bir şeyi qeyd etməyə dəyər:
Polimorfizm və onun dostları - 9
Yəni, həddən artıq yükləmə zamanı kompilyator düzgünlüyünü yoxlayır. Vacibdir. Bəs kompilyator müəyyən bir metodun çağırılması lazım olduğunu necə müəyyən edir? O, Java dilinin spesifikasiyasında təsvir edilən "Ən Xüsusi Metod" qaydasından istifadə edir: " 15.12.2.5. Ən Xüsusi Metodun Seçilməsi ". Bunun necə işlədiyini nümayiş etdirmək üçün Oracle Certified Professional Java Programmer-dən nümunə götürək:
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);
  }
}
Buradan nümunə götürün: https://github.com/stokito/OCPJP/blob/master/src/ru/habrahabr/blogs/java/OCPJP1/question1/Overload.j... Gördüyünüz kimi, biz keçirik. metoda sıfır. Kompilyator ən spesifik növü müəyyən etməyə çalışır. Obyekt uyğun deyil, çünki hər şey ondan miras qalıb. Davam et. 2 sinif istisnalar var. Gəlin java.io.IOException- a baxaq və görək ki, “Birbaşa məlum alt siniflər”də FileNotFoundException var. Yəni məlum olur ki, FileNotFoundException ən spesifik tipdir. Beləliklə, nəticə "FileNotFoundException" sətirinin çıxışı olacaq. Amma IOException-ı EOFException ilə əvəz etsək, belə çıxır ki, tip ağacında iyerarxiyanın eyni səviyyəsində iki metodumuz var, yəni onların hər ikisi üçün IOException anadır. Kompilyator hansı metodu çağıracağını seçə bilməyəcək və kompilyasiya xətası verəcək: reference to method is ambiguous. Daha bir misal:
public class Overload{
    public static void method(int... array) {
        System.out.println("1");
    }

    public static void main(String args[]) {
        method(1, 2);
    }
}
1 çıxacaq. Burada heç bir sual yoxdur. int... növü vararg https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html və həqiqətən "sintaktik şəkər"dən başqa bir şey deyil və əslində bir intdir. .. massivi int[] massivi kimi oxumaq olar. İndi bir üsul əlavə etsək:
public static void method(long a, long b) {
	System.out.println("2");
}
Sonra 1 yox, 2 göstərəcək, çünki biz 2 rəqəm keçirik və 2 arqument bir massivdən daha yaxşı uyğun gəlir. Bir üsul əlavə etsək:
public static void method(Integer a, Integer b) {
	System.out.println("3");
}
Onda biz hələ də 2-ni görəcəyik. Çünki bu halda primitivlər Tam ədəddə boksdan daha dəqiq uyğunluq təşkil edir. Bununla belə, icra etsək, method(new Integer(1), new Integer(2));3-ü çap edəcək. Java-da konstruktorlar metodlara bənzəyir və onlar imza əldə etmək üçün də istifadə oluna bildikləri üçün həddindən artıq yüklənmiş metodlar kimi eyni “aşırı yükləmə həlli” qaydaları onlara tətbiq edilir. Java dilinin spesifikasiyası bunu " 8.8.8. Konstruktorun həddindən artıq yüklənməsi " bölməsində izah edir. Metodun həddən artıq yüklənməsi = Erkən bağlama (aka Statik Bağlama) Siz tez-tez Statik Bağlama və ya Dinamik Bağlama kimi tanınan erkən və gec bağlama haqqında eşidə bilərsiniz. Onların arasındakı fərq çox sadədir. Erkən tərtib, gec isə proqramın icra olunduğu andır. Buna görə də, erkən bağlama (statik bağlama) tərtib zamanı hansı metodun kimə çağırılacağının müəyyən edilməsidir. Yaxşı, gec bağlama (dinamik bağlama) proqramın icrası zamanı birbaşa hansı metodun çağırılacağının müəyyən edilməsidir. Daha əvvəl gördüyümüz kimi (biz IOException-ı EOFException-a dəyişdikdə), əgər metodları həddən artıq yükləsək ki, kompilyator hansı zəngi harada edəcəyini başa düşə bilməsin, onda biz kompilyasiya vaxtı xətası alacağıq: metoda istinad birmənalı deyil. İngilis dilindən tərcümədə qeyri-müəyyən söz çoxmənalı və ya qeyri-müəyyən, qeyri-müəyyən deməkdir. Belə çıxır ki, həddindən artıq yüklənmə erkən bağlanır, çünki yoxlama tərtib zamanı həyata keçirilir. Nəticələrimizi təsdiqləmək üçün “ 8.4.9. Həddindən artıq yükləmə ” bölməsində Java dilinin spesifikasiyasını açaq :
Polimorfizm və onun dostları - 10
Məlum olub ki, tərtib zamanı metodun imzasını müəyyən etmək üçün arqumentlərin növləri və sayı haqqında məlumatlardan (toplama zamanı mövcud olan) istifadə olunacaq. Metod obyektin metodlarından biridirsə (yəni, nümunə metodu), faktiki metod çağırışı dinamik metod axtarışından (yəni, dinamik bağlama) istifadə edərək icra zamanı müəyyən ediləcək. Daha aydın olmaq üçün əvvəllər müzakirə edilənə bənzər bir nümunə götürək:
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);
    }
}
Gəlin bu kodu HelloWorld.java faylında saxlayaq və istifadə edərək kompilyasiya edək. javac HelloWorld.java İndi isə kompilyatorumuzun bayt kodunda nə yazdığını görək: javap -verbose HelloWorld.
Polimorfizm və onun dostları - 11
Qeyd edildiyi kimi, kompilyator gələcəkdə hansısa virtual metodun çağırılacağını müəyyən etmişdir. Yəni metodun gövdəsi iş vaxtında müəyyən ediləcək. Lakin tərtib zamanı hər üç üsuldan tərtibçi ən uyğununu seçdi, ona görə də nömrəni göstərdi:"invokevirtual #13"
Polimorfizm və onun dostları - 12
Bu hansı üsuldur? Bu üsula bir keçiddir. Təxminən desək, bu, işləmə zamanı Java Virtual Maşının icra etmək üçün hansı metodu axtaracağını müəyyən edə biləcəyi bəzi ipucudur. Daha ətraflı məlumatı super məqalədə tapa bilərsiniz: " JVM daxili olaraq həddindən artıq yüklənmə və ləğvetmə metodunu necə idarə edir ".

Xülasə

Beləliklə, Java-nın obyekt yönümlü bir dil olaraq polimorfizmi dəstəklədiyini öyrəndik. Polimorfizm statik (Statik Bağlama) və ya dinamik (Dinamik Bağlama) ola bilər. Erkən bağlama kimi tanınan statik polimorfizmlə tərtibçi hansı metodun harada və harada çağırılacağını müəyyənləşdirir. Bu, həddindən artıq yükləmə kimi bir mexanizmdən istifadə etməyə imkan verir. Metodun əvvəllər hesablanmış imzasına əsaslanaraq, gec bağlama kimi tanınan dinamik polimorfizmlə hansı obyektin istifadə edildiyinə (yəni, hansı obyektin metodunun çağırıldığına) görə metod iş vaxtında hesablanacaq. Bu mexanizmlərin necə işlədiyini bayt kodundan istifadə etməklə görmək olar. Həddindən artıq yükləmə metodun imzalarına baxır və həddindən artıq yüklənməni həll edərkən ən konkret (ən dəqiq) seçim seçilir. Üstün təyinetmə, hansı metodların mövcud olduğunu müəyyən etmək üçün növə baxır və metodların özləri obyekt əsasında çağırılır. Mövzu ilə bağlı materiallarla yanaşı: #Viaçeslav
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION