JavaRush /Blog Jawa /Random-JV /Polimorfisme lan kanca-kancane
Viacheslav
tingkat

Polimorfisme lan kanca-kancane

Diterbitake ing grup
Polimorfisme minangka salah sawijining prinsip dhasar pemrograman berorientasi obyek. Iki ngidini sampeyan nggunakake kekuwatan ngetik Jawa sing kuwat lan nulis kode sing bisa digunakake lan bisa dijaga. Akeh sing wis ngomong babagan dheweke, nanging muga-muga kabeh wong bisa njupuk sing anyar saka review iki.
Polimorfisme lan kanca-kancane - 1

Pambuka

Aku kabeh ngerti yen basa pemrograman Java kalebu Oracle. Mulane, path kita wiwit karo situs: www.oracle.com . Ana "Menu" ing kaca utama. Ing bagean kasebut, ing bagean "Dokumentasi" ana bagean "Jawa". Kabeh sing ana gandhengane karo fungsi dhasar basa kasebut kalebu "dokumentasi Jawa SE", mula kita milih bagean iki. Bagean dokumentasi bakal mbukak kanggo versi paling anyar, nanging saiki "Nggoleki rilis sing beda?" Ayo milih opsi: JDK8. Ing kaca kita bakal weruh akeh opsi beda. Nanging kita kasengsem ing Sinau Basa: " Tutorial Java Paths Learning ". Ing kaca iki kita bakal nemokake bagean liya: " Sinau Basa Jawa ". Iki minangka sing paling suci, tutorial babagan dhasar Jawa saka Oracle. Java minangka basa pemrograman berorientasi obyek (OOP), mula sinau basa kasebut sanajan ing situs web Oracle diwiwiti kanthi diskusi babagan konsep dhasar " Konsep Pemrograman Berorientasi Objek ". Saka jeneng kasebut jelas yen Jawa fokus ing nggarap obyek. Saking subbagian “ Apa Itu Obyek? ” cetha yen objek ing Jawa dumadi saka kahanan lan solah bawa. Mbayangno yen kita duwe akun bank. Jumlah dhuwit ing akun minangka negara, lan cara nggarap negara iki minangka prilaku. Obyek kudu diterangake piye wae (marang negara lan prilaku apa wae) lan deskripsi iki kelas . Nalika kita nggawe obyek saka sawetara kelas, kita nemtokake kelas iki lan iki disebut " jinis obyek ". Mula diarani basa Jawa iku basa kang ketik banget, kaya kang kaandharake ing spesifikasi basa Jawa ing perangan “ Bab 4. Jinis, Nilai, lan Variabel “. Basa Jawa nderek konsep OOP lan ndhukung warisan nggunakake tembung kunci extends. Kenapa ekspansi? Amarga karo warisan, kelas anak marisi prilaku lan negara kelas induk lan bisa nglengkapi, i.e. ngluwihi fungsi saka kelas dhasar. Antarmuka uga bisa ditemtokake ing deskripsi kelas nggunakake tembung kunci implements. Nalika kelas ngleksanakake antarmuka, iku tegese kelas conforms kanggo sawetara kontrak - pranyatan dening programmer kanggo liyane saka lingkungan sing kelas wis prilaku tartamtu. Contone, pamuter wis macem-macem tombol. Tombol iki antarmuka kanggo kontrol prilaku pamuter, lan prilaku bakal ngganti negara internal pamuter (Contone, volume). Ing kasus iki, negara lan prilaku minangka gambaran bakal menehi kelas. Yen kelas ngleksanakake antarmuka, banjur obyek digawe dening kelas iki bisa diterangake dening jinis ora mung kelas, nanging uga antarmuka. Ayo ndeleng conto:
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();
    }
}
Jinis minangka katrangan sing penting banget. Iku ngandhani carane kita bakal bisa karo obyek, i.e. prilaku apa kita nyana saka obyek. Prilaku minangka metode. Mulane, ayo padha ngerti cara. Ing situs web Oracle, metode duwe bagean dhewe ing Tutorial Oracle: " Defining Methods ". Bab pisanan sing kudu dijupuk saka artikel: Tandha saka metode yaiku jeneng metode lan jinis paramèter :
Polimorfisme lan kanca-kancane - 2
Contone, nalika ngumumake metode metode void umum (Obyek o), tandhane bakal dadi jeneng metode lan jinis Obyek parameter. Jinis bali ora kalebu ing teken. Iku penting! Sabanjure, ayo ngumpulake kode sumber kita. Kaya sing dingerteni, kode kasebut kudu disimpen ing file kanthi jeneng kelas lan ekstensi java. Kode Java dikompilasi nggunakake kompiler " javac " dadi sawetara format penengah sing bisa dieksekusi dening Java Virtual Machine (JVM). Format penengah iki diarani bytecode lan ana ing file kanthi ekstensi .class. Ayo mbukak printah kanggo ngumpulake: javac MusicPlayer.java Sawise kode java dikompilasi, kita bisa nglakokake. Nggunakake utilitas " java " kanggo miwiti, proses mesin virtual java bakal diluncurake kanggo nglakokake bytecode sing dilewati ing file kelas. Ayo mbukak printah kanggo mbukak aplikasi: java MusicPlayer. Kita bakal weruh ing layar teks kasebut ing parameter input cara println. Apike, duwe bytecode ing file karo extension .class, kita bisa ndeleng nggunakake utilitas " javap ". Ayo mbukak printah <ocde>javap -c MusicPlayer:
Polimorfisme lan kanca-kancane - 3
Saka bytecode, kita bisa ndeleng manawa nelpon metode liwat obyek sing jinis kelas kasebut ditemtokake nggunakake invokevirtual, lan kompiler wis ngetung cara teken sing kudu digunakake. kenging menapa invokevirtual? Amarga ana telpon (invoke diterjemahake minangka nelpon) saka cara virtual. Apa metode virtual? Iki minangka cara sing awak bisa ditindhes sajrone eksekusi program. Bayangake sampeyan duwe dhaptar korespondensi ing antarane kunci tartamtu (tandha metode) lan awak (kode) metode kasebut. Lan korespondensi antarane tombol lan awak metode kasebut bisa diganti sajrone eksekusi program. Mulane cara kasebut virtual. Secara default, ing Jawa, cara sing ora statis, ora final, lan ora pribadi iku virtual. Thanks kanggo iki, Jawa ndhukung prinsip pemrograman berorientasi obyek polimorfisme. Minangka sampeyan wis ngerti, iki minangka review kita saiki.

Polimorfisme

Ing situs web Oracle ing Tutorial resmi ana bagean sing kapisah: " Polimorfisme ". Ayo nggunakake Java Online Compiler kanggo ndeleng cara polimorfisme ing Jawa. Contone, kita duwe sawetara kelas abstrak Nomer sing makili nomer ing Jawa. Apa sing ngidini? Dheweke duwe sawetara teknik dhasar sing bakal diduweni kabeh ahli waris. Sapa wae sing marisi saka Nomer kanthi harfiah ujar - "Aku nomer, sampeyan bisa nggarap aku minangka nomer." Contone, kanggo penerus sembarang sampeyan bisa nggunakake intValue () cara kanggo njaluk Nilai Integer sawijining. Yen sampeyan ndeleng java api kanggo Nomer, sampeyan bisa ndeleng manawa metode kasebut abstrak, yaiku, saben penerus Nomer kudu ngetrapake metode kasebut dhewe. Nanging apa iki menehi kita? Ayo katon ing conto:
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));
    }
}
Minangka bisa dideleng saka conto, thanks kanggo polymorphism, kita bisa nulis cara sing bakal nampa bantahan saka sembarang tipe minangka input, kang bakal dadi turunan saka Number (kita ora bisa njaluk Nomer, amarga iku kelas abstrak). Kaya sing kedadeyan karo conto pamuter, ing kasus iki kita ujar manawa kita pengin nggarap, kaya Nomer. Kita ngerti manawa sapa wae sing dadi Nomer kudu bisa nyedhiyakake nilai integer. Lan iku cukup kanggo kita. Kita ora pengin pindhah menyang rincian implementasine saka obyek tartamtu lan pengin bisa karo obyek iki liwat cara umum kanggo kabeh turunane Number. Dhaptar metode sing bakal kasedhiya kanggo kita bakal ditemtokake dening jinis ing wektu kompilasi (kaya sing kita deleng sadurunge ing bytecode). Ing kasus iki, jinis kita bakal nomer. Minangka sampeyan bisa ndeleng saka conto, kita ngliwati nomer beda saka macem-macem jinis, yaiku, cara summ bakal nampa Integer, Long, lan Double minangka input. Nanging sing padha duwe umum yaiku keturunan saka Nomer abstrak, lan mulane nolak prilaku ing metode intValue, amarga saben jinis tartamtu ngerti carane matak jinis sing kanggo Integer. Polimorfisme kasebut dileksanakake liwat sing diarani overriding, ing Inggris Overriding.
Polimorfisme lan kanca-kancane - 4
Overriding utawa polimorfisme dinamis. Dadi, ayo miwiti nyimpen file HelloWorld.java kanthi isi ing ngisor iki:
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();
    }
}
Ayo javac HelloWorld.javalan javap -c HelloWorld:
Polimorfisme lan kanca-kancane - 5
Nalika sampeyan bisa ndeleng, ing bytecode kanggo baris karo telpon cara, referensi padha kanggo cara kanggo nelpon dituduhake invokevirtual (#6). ayo gawe java HelloWorld. Kaya sing kita deleng, variabel induk lan anak diumumake kanthi jinis Parent, nanging implementasine dhewe diarani miturut obyek sing ditugasake menyang variabel (yaiku jinis obyek). Sajrone eksekusi program (uga ngandika ing runtime), JVM, gumantung ing obyek, nalika nelpon cara nggunakake teken padha, kaleksanan cara beda. Sing, nggunakake tombol teken sing cocog, kita pisanan nampa siji cara awak, lan banjur nampa liyane. Gumantung apa obyek ing variabel. Penentuan iki ing wektu eksekusi program cara sing bakal diarani uga diarani late binding utawa Dynamic Binding. Yaiku, cocog antarane teken lan awak metode ditindakake kanthi dinamis, gumantung saka obyek sing diarani metode kasebut. Mesthi, sampeyan ora bisa ngalahake anggota statis saka kelas (anggota kelas), uga anggota kelas karo jinis akses pribadi utawa final. @Override anotasi uga teka kanggo bantuan saka pangembang. Iki mbantu kompiler ngerti yen ing wektu iki kita bakal ngilangi prilaku metode leluhur. Yen kita nggawe kesalahan ing tandha cara, kompiler bakal langsung ngandhani babagan iki. Tuladhane:
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");
        }
}
Ora ngumpulake kesalahan: kesalahan: cara ora ngilangi utawa ngetrapake metode saka supertype
Polimorfisme lan kanca-kancane - 6
Redefinisi uga digandhengake karo konsep " kovarian ". Ayo katon ing conto:
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());
    }
}
Senadyan abstruseness katon, makna nerangake kasunyatan sing nalika overriding, kita bisa bali ora mung jinis sing wis kasebut ing leluhur, nanging uga jinis liyane tartamtu. Contone, leluhur bali Number, lan kita bisa bali Integer - turunan saka Number. Padha ditrapake kanggo pangecualian ngumumaké ing cara kang mbalang. Ahli waris bisa ngatasi cara kasebut lan nyaring pengecualian sing dibuwang. Nanging dheweke ora bisa nggedhekake. Yaiku, yen wong tuwa mbuwang IOException, mula kita bisa mbuwang EOFException sing luwih tepat, nanging ora bisa mbuwang Exception. Kajaba iku, sampeyan ora bisa mbatesi ruang lingkup lan sampeyan ora bisa ngetrapake watesan tambahan. Contone, sampeyan ora bisa nambah statis.
Polimorfisme lan kanca-kancane - 7

ndhelikake

Ana uga sing diarani " concealment ". Tuladha:
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();
    }
}
Iki cukup jelas yen sampeyan mikir babagan iki. Anggota statis saka kelas kalebu kelas, i.e. menyang jinis variabel. Mulane, logis yen anak saka jinis Parent, banjur cara bakal disebut ing Parent, lan ora ing anak. Yen kita ndeleng bytecode, kaya sing ditindakake sadurunge, kita bakal weruh manawa metode statis diarani nggunakake invokestatic. Iki nerangake JVM sing kudu katon ing jinis, lan ora ing tabel cara, minangka invokevirtual utawa invokeinterface iya.
Polimorfisme lan kanca-kancane - 8

Cara overloading

Apa maneh sing kita deleng ing Tutorial Oracle Jawa? Ing bagean sadurunge sinau " Metode Nemtokake " ana bab Overloading. Opo iki? Ing basa Rusia iki "metode overloading", lan cara kasebut diarani "overloaded". Dadi, overloading metode. Ing kawitan marketing, kabeh iku prasaja. Ayo mbukak compiler Java online, contone 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);
	}
}
Dadi, kabeh katon prasaja ing kene. Kaya sing kasebut ing tutorial Oracle, cara sing kakehan (ing kasus iki cara ngomong) beda karo jumlah lan jinis argumen sing diterusake menyang metode kasebut. Sampeyan ora bisa ngumumake jeneng sing padha lan jumlah sing padha karo jinis argumen sing padha, amarga compiler ora bakal bisa kanggo mbedakake saka saben liyane. Perlu dicathet bab sing penting banget:
Polimorfisme lan kanca-kancane - 9
Sing, nalika overloading, compiler mriksa bener. Iku penting. Nanging carane compiler bener nemtokake cara tartamtu kudu disebut? Iki nggunakake aturan "Metode Paling Spesifik" sing diterangake ing spesifikasi basa Jawa: " 15.12.2.5. Milih Cara Paling Spesifik ". Kanggo nduduhake cara kerjane, ayo njupuk conto saka 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);
  }
}
Njupuk conto saka kene: https://github.com/stokito/OCPJP/blob/master/src/ru/habrahabr/blogs/java/OCPJP1/question1/Overload.j... Nalika sampeyan bisa ndeleng, kita liwat null kanggo metode. Compiler nyoba nemtokake jinis sing paling spesifik. Obyek ora cocok amarga kabeh iku warisan saka dheweke. Terusna. Ana 2 kelas pengecualian. Ayo goleki java.io.IOException lan deleng manawa ana FileNotFoundException ing "Subkelas sing Dikenal Langsung". Tegese, ternyata FileNotFoundException minangka jinis sing paling spesifik. Mulane, asil bakal dadi output saka string "FileNotFoundException". Nanging yen kita ngganti IOException karo EOFException, dadi metu sing kita duwe rong cara ing tingkat padha hirarki ing wit jinis, sing, kanggo loro, IOException punika tiyang sepah. Compiler ora bakal bisa milih cara kanggo nelpon lan bakal uncalan kesalahan kompilasi reference to method is ambiguous:. Conto liyane:
public class Overload{
    public static void method(int... array) {
        System.out.println("1");
    }

    public static void main(String args[]) {
        method(1, 2);
    }
}
Iku bakal output 1. Ora ana pitakonan ing kene. Jinis int ... punika vararg https://docs.oracle.com/javase/8/docs/technotes/guides/language/varargs.html lan pancene ora luwih saka "gula sintaksis" lan bener int. .. larik bisa diwaca minangka int [] larik. Yen saiki kita nambah cara:
public static void method(long a, long b) {
	System.out.println("2");
}
Banjur bakal nampilake ora 1, nanging 2, amarga kita liwat 2 nomer, lan 2 bantahan sing cocog luwih saka siji Uploaded. Yen kita nambah cara:
public static void method(Integer a, Integer b) {
	System.out.println("3");
}
Banjur kita isih bakal weruh 2. Amarga ing kasus iki, primitif minangka pertandhingan sing luwih pas tinimbang tinju ing Integer. Nanging, yen kita nglakokaké, method(new Integer(1), new Integer(2));bakal print 3. Konstruktor ing Jawa padha karo cara, lan wiwit padha uga bisa digunakake kanggo diwenehi teken, padha "resolusi overloading" aturan kanggo wong-wong mau minangka cara overloaded. Ing specification basa Jawa marang kita supaya ing " 8.8.8. Constructor Overloading ". Cara kakehan = Ikatan awal (alias Ikatan Statis) Sampeyan kerep krungu bab ikatan awal lan pungkasan, uga dikenal minangka Binding Statis utawa Binding Dinamis. Bentenipun antarane wong-wong mau banget prasaja. Awal iku kompilasi, telat iku wayahe program dieksekusi. Mula, ikatan awal (static binding) yaiku nemtokake cara sing bakal diarani sapa ing wektu kompilasi. Inggih, late binding (dynamic binding) punika nemtokake cara kanggo nelpon langsung ing wektu eksekusi program. Kaya sing kita deleng sadurunge (nalika kita ngganti IOException dadi EOFException), yen kita kakehan cara supaya kompiler ora ngerti ngendi arep nelpon, mula kita bakal entuk kesalahan kompilasi-wektu: referensi kanggo metode ambigu. Tembung ambigu sing diterjemahake saka basa Inggris tegese ambigu utawa ora mesthi, ora tepat. Pranyata metu sing kakehan awal naleni, amarga mriksa dileksanakake ing wektu kompilasi. Kanggo konfirmasi kesimpulan, ayo mbukak Spesifikasi Basa Jawa ing bab " 8.4.9. Overloading ":
Polimorfisme lan kanca-kancane - 10
Pranyata sajrone kompilasi, informasi babagan jinis lan jumlah argumen (sing kasedhiya ing wektu kompilasi) bakal digunakake kanggo nemtokake tanda tangan metode kasebut. Yen metode kasebut minangka salah sawijining metode obyek (yaiku, metode conto), panggilan metode sing nyata bakal ditemtokake nalika runtime nggunakake lookup metode dinamis (yaiku, ikatan dinamis). Supaya luwih cetha, ayo njupuk conto sing padha karo sing wis dibahas sadurunge:
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);
    }
}
Ayo simpen kode iki menyang file HelloWorld.java lan ngumpulake nggunakake javac HelloWorld.java Saiki ayo ndeleng apa sing ditulis kompiler ing bytecode kanthi nglakokake printah: javap -verbose HelloWorld.
Polimorfisme lan kanca-kancane - 11
Kaya sing wis dingerteni, kompiler wis nemtokake manawa sawetara metode virtual bakal diarani ing mangsa ngarep. Yaiku, awak metode bakal ditetepake nalika runtime. Nanging ing wektu kompilasi, saka kabeh telung cara, kompiler milih sing paling cocok, mula nuduhake nomer kasebut:"invokevirtual #13"
Polimorfisme lan kanca-kancane - 12
Apa jenis methodref iki? Iki minangka link menyang metode kasebut. Kira-kira, iki minangka pitunjuk sing, nalika runtime, Mesin Virtual Java bisa nemtokake cara sing kudu ditindakake. Rincian liyane bisa ditemokake ing artikel super: " Carane JVM Nangani Metode Overloading Lan Overriding Internal ".

Ringkesan

Dadi, kita nemokake manawa Jawa, minangka basa berorientasi obyek, ndhukung polimorfisme. Polimorfisme bisa dadi statis (Static Binding) utawa dinamis (Dynamic Binding). Kanthi polimorfisme statis, uga dikenal minangka ikatan awal, kompiler nemtokake cara sing kudu diarani lan ing ngendi. Iki ngidini nggunakake mekanisme kayata overload. Kanthi polimorfisme dinamis, uga dikenal minangka ikatan telat, adhedhasar tandha cara sing wis diwilang sadurunge, sawijining metode bakal diwilang nalika runtime adhedhasar obyek sing digunakake (yaiku, metode obyek sing diarani). Cara kerja mekanisme kasebut bisa dideleng nggunakake bytecode. Kakehan katon ing tandha cara, lan nalika ngrampungake kakehan, pilihan sing paling spesifik (paling akurat) dipilih. Overriding katon ing jinis kanggo nemtokake cara kasedhiya, lan cara dhewe disebut adhedhasar obyek. Uga materi babagan topik: #Viacheslav
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION