JavaRush /Blog Java /Random-MS /Warisan sebagai fenomena
articles
Tahap

Warisan sebagai fenomena

Diterbitkan dalam kumpulan
Sejujurnya, saya pada mulanya tidak merancang artikel ini. Isu yang ingin saya bincangkan di sini saya anggap remeh, malah tidak patut disebut. Walau bagaimanapun, dalam proses menulis artikel untuk laman web ini, saya membangkitkan perbincangan tentang warisan berbilang dalam salah satu forum. Akibatnya, ternyata kebanyakan pembangun mempunyai pemahaman yang sangat kabur tentang warisan. Dan, dengan itu, dia membuat banyak kesilapan. Memandangkan warisan adalah salah satu ciri OOP yang paling penting (jika bukan yang paling penting!), saya memutuskan untuk menumpukan artikel berasingan untuk fenomena ini. * * * Pertama, saya ingin membezakan antara dua konsep - objek dan kelas. Konsep-konsep ini sentiasa keliru. Sementara itu, mereka adalah pusat kepada OOP. Dan, pada pendapat saya, adalah perlu untuk mengetahui perbezaan antara mereka. Jadi, objek. Pada asasnya, ia adalah apa-apa. Inilah kiubnya. Kayu, biru. Panjang tepi ialah 5 cm Ini ialah objek. Dan ada piramid. Plastik, merah. 10 cm rusuk. Ini juga objek. Apa persamaan mereka? Saiz yang berbeza. Berbeza bentuk. Bahan yang berbeza. Namun, mereka mempunyai persamaan. Pertama sekali, kedua-dua kubus dan piramid adalah polyhedra biasa. Itu. hasil tambah bilangan bucu dan bilangan muka adalah 2 lebih daripada bilangan tepi. Selanjutnya. Kedua-dua bentuk mempunyai muka, tepi dan bucu. Kedua-dua angka mempunyai ciri seperti saiz rusuk. Kedua-dua bentuk boleh diputar. Kedua-dua rajah boleh dilukis. Dua sifat terakhir sudah menjadi tingkah laku. Dan sebagainya. Amalan pengaturcaraan menunjukkan bahawa lebih mudah untuk beroperasi dengan objek homogen daripada objek heterogen. Dan kerana masih terdapat persamaan antara angka-angka ini, ada keinginan untuk menyerlahkan persamaan ini. Di sinilah konsep kelas dimainkan. Jadi, definisi.
Kelas ialah deskriptor bagi sifat umum sekumpulan objek. Sifat ini boleh menjadi kedua-dua ciri objek (saiz, berat, warna, dll.), dan tingkah laku, peranan, dsb.
Komen. Perkataan "semua" (penerangan semua sifat) tidak disebut. Ini bermakna bahawa mana-mana objek boleh tergolong dalam beberapa kelas yang berbeza. Warisan sebagai fenomena - 1 Mari kita ambil contoh yang sama dengan bentuk geometri sebagai asas. Penerangan yang paling umum ialah polyhedron biasa . Tidak kira saiz tepi, bilangan muka dan bucu. Satu-satunya perkara yang kita tahu ialah rajah ini mempunyai bucu, tepi dan muka, dan panjang tepi adalah sama. Selanjutnya. Kita boleh membuat penerangan lebih spesifik. Katakan kita mahu melukis polihedron ini . Marilah kita memperkenalkan konsep sedemikian sebagai polihedron sekata yang dilukis . Apa yang kita perlukan untuk melukis? Perihalan kaedah lukisan umum yang tidak bergantung pada koordinat puncak tertentu. Mungkin warna objek. Sekarang mari kita perkenalkan kelas Cube dan Tetrahedron . Objek kepunyaan kelas ini sememangnya polyhedra biasa. Satu-satunya perbezaan ialah bilangan bucu, tepi dan muka sudah ditetapkan dengan ketat untuk setiap kelas baharu. Selanjutnya, mengetahui jenis angka tertentu, kita boleh memberikan penerangan tentang kaedah lukisan. Ini bermakna bahawa mana-mana objek kelas Kubus atau Tetrahedron juga merupakan objek kelas polihedron biasa yang dilukis . Terdapat hierarki kelas. Dalam hierarki ini kita turun daripada penerangan yang paling umum kepada yang paling khusus. Ambil perhatian bahawa objek bagi mana-mana kelas juga sesuai dengan perihalan mana-mana kelas yang lebih umum dalam hierarki. Hubungan kelas ini dipanggil warisan . Setiap kelas anak mewarisi semua sifat induk, lebih umum, dan (mungkin) menambahkan beberapa sifatnya sendiri pada sifat ini. Atau ia mengatasi beberapa sifat kelas induk. Di sini saya ingin memetik daripada buku klasik Gradi Bucha mengenai reka bentuk berorientasikan objek:
Oleh itu, warisan mentakrifkan hierarki "adalah" antara kelas, di mana subkelas mewarisi daripada satu atau lebih superclass. Ini sebenarnya adalah ujian litmus untuk pewarisan. Memandangkan kelas A dan B, jika A "bukan" jenis B, maka A tidak sepatutnya menjadi subkelas B.
Diterjemah bunyinya seperti ini:
Oleh itu, warisan mentakrifkan hierarki "adalah" antara kelas, di mana subkelas mewarisi daripada satu atau lebih superclass. Ini, sebenarnya, ujian penentu (secara literal, ujian litmus, nota saya) untuk pewarisan. Jika kita mempunyai kelas A dan B, dan jika kelas A "bukan" varian kelas B, maka A mestilah bukan subkelas B.
Mereka yang telah membaca sejauh ini mungkin akan memutar-mutar jari mereka ke pelipis mereka dalam kebingungan. Pemikiran pertama adalah bahawa ini adalah remeh! Ini adalah benar. Tetapi jika anda tahu berapa banyak hierarki warisan yang gila yang saya lihat! Dalam perbincangan yang saya nyatakan pada awal-awal lagi, salah seorang peserta agak serius mewarisi kereta kebal daripada... mesingan!!! Atas sebab mudah kereta kebal itu MEMPUNYAI mesingan. Dan ini adalah kesilapan yang paling biasa. Warisan dikelirukan dengan pengagregatan - kemasukan satu objek dalam yang lain. Kereta kebal itu bukan mesingan, ia mengandungi satu. Dan kerana ralat ini, selalunya terdapat keinginan untuk menggunakan pelbagai warisan. Sekarang mari kita beralih terus ke Java. Apa yang ada dari segi harta pusaka? Terdapat dua jenis kelas dalam bahasa - kelas yang boleh mengandungi pelaksanaan dan kelas yang tidak boleh berbuat demikian. Yang terakhir dipanggil antara muka, walaupun pada dasarnya mereka adalah kelas abstrak sepenuhnya. Warisan sebagai fenomena - 2 Jadi, bahasa tersebut membolehkan anda mewarisi kelas daripada kelas lain yang berpotensi mengandungi pelaksanaan. TETAPI HANYA DARI SATU! Biar saya jelaskan mengapa ini dilakukan. Intinya ialah setiap pelaksanaan hanya boleh menangani bahagiannya - dengan pembolehubah dan kaedah yang diketahuinya. Dan walaupun kita mewarisi kelas C daripada A dan B , maka kaedah processA , yang diwarisi daripada kelas A, hanya boleh berfungsi dengan pembolehubah dalaman a , kerana ia tidak tahu apa-apa tentang b , sama seperti ia tidak tahu apa-apa tentang c dan kaedah processC . Begitu juga kaedah processB hanya boleh berfungsi dengan pembolehubah b. Iaitu, pada dasarnya, bahagian yang diwarisi diasingkan. Kelas C sudah tentu boleh berfungsi dengan mereka, tetapi ia juga boleh berfungsi dengan bahagian ini jika ia hanya disertakan sebagai sebahagian daripadanya dan bukannya diwarisi. Namun, terdapat satu lagi gangguan di sini, iaitu pertindihan nama. Jika kaedah processA dan processB dinamakan sama, katakan proses, maka apakah kesan yang akan ada pada memanggil kaedah proses kelas C ? Antara dua kaedah yang manakah akan dipanggil? Sudah tentu, C++ mempunyai kawalan dalam situasi ini, tetapi ini tidak menambah keharmonian bahasa. Jadi, pewarisan pelaksanaan tidak memberikan kelebihan, tetapi terdapat kelemahan. Atas sebab ini, warisan pelaksanaan di Jawa ini telah ditinggalkan. Walau bagaimanapun, pembangun dibiarkan dengan pilihan sedemikian untuk berbilang warisan sebagai warisan daripada antara muka. Dalam istilah Java, pelaksanaan antara muka. Apakah antara muka? Satu set kaedah. (Kami tidak sedang mempertimbangkan takrif pemalar dalam antara muka; lebih lanjut mengenainya di sini .) Apakah kaedah? Dan kaedah, pada terasnya, menentukan tingkah laku objek. Bukan kebetulan bahawa nama hampir setiap kaedah mengandungi tindakan - getXXX , drawXXX , countXXX , dsb. Dan oleh kerana antara muka ialah koleksi kaedah, antara muka sebenarnya adalah penentu tingkah laku . Pilihan lain untuk menggunakan antara muka adalah untuk menentukan peranan objek. Pemerhati, Pendengar , dsb. Dalam kes ini, kaedah itu sebenarnya merupakan penjelmaan tindak balas kepada beberapa peristiwa luaran. Iaitu, sekali lagi, tingkah laku. Objek sudah tentu boleh mempunyai beberapa tingkah laku yang berbeza. Jika ia perlu diberikan, ia diberikan. Jika dia perlu diselamatkan, dia diselamatkan. Nah, dll. Sehubungan itu, keupayaan untuk mewarisi daripada kelas yang mentakrifkan tingkah laku adalah sangat, sangat berguna. Begitu juga, objek boleh mempunyai beberapa peranan yang berbeza. Namun, pelaksanaantingkah laku adalah sepenuhnya atas hati nurani kelas kanak-kanak. Warisan daripada antara muka (pelaksanaannya) mengatakan bahawa objek kelas ini sepatutnya dapat melakukan ini dan itu. Dan BAGAIMANA ia melakukan ini ditentukan secara bebas oleh setiap kelas yang melaksanakan antara muka. Mari kembali kepada kesilapan dalam pewarisan. Pengalaman saya dalam membangunkan pelbagai sistem menunjukkan bahawa mempunyai warisan daripada antara muka, anda boleh melaksanakan sebarang sistem tanpa menggunakan warisan pelaksanaan berbilang. Oleh itu, apabila saya menghadapi aduan tentang kekurangan pelbagai warisan dalam bentuk yang wujud dalam C++, bagi saya ini adalah tanda pasti reka bentuk yang salah. Kesilapan yang paling biasa dilakukan ialah yang telah saya sebutkan - warisan dikelirukan dengan pengagregatan. Kadang-kadang ini berlaku kerana andaian yang salah. Itu. Ambil, sebagai contoh, meter kelajuan, dikatakan bahawa kelajuan hanya boleh diukur dengan mengukur jarak dan masa, selepas itu meter kelajuan berjaya diwarisi daripada pembaris dan jam, dengan itu menjadi pembaris dan jam, mengikut definisi harta pusaka. (Permintaan saya untuk mengukur masa dengan meter kelajuan biasanya dijawab dengan jenaka. Atau mereka tidak menjawab langsung.) Apakah kesilapan di sini? Dalam premis. Hakikatnya ialah meter kelajuan tidak mengukur masa. Dan jarak, dengan cara, juga. Odometer, yang terdapat dalam mana-mana meter kelajuan, ialah contoh klasik peranti kedua dalam perumahan yang sama, i.e. pengagregatan. Ia tidak diperlukan untuk mengukur kelajuan. Ia boleh dialih keluar sama sekali - ini tidak akan menjejaskan pengukuran kelajuan dalam apa cara sekalipun. Kadang-kadang kesilapan sedemikian dilakukan dengan sengaja. Ini lebih teruk. "Ya, saya tahu ia salah, tetapi ia lebih mudah untuk saya." Apa yang boleh menyebabkan ini? Tetapi inilah yang: kita akan mewarisi kereta kebal daripada meriam dan mesingan. Ia lebih mudah dengan cara ini. Akibatnya, kereta kebal itu menjadi meriam dan mesingan. Seterusnya kita akan melengkapkan pesawat dengan dua mesingan dan meriam. Apa yang kita dapat? Sebuah pesawat dengan senjata yang digantung dalam bentuk tiga kereta kebal! Kerana PASTI ada orang yang tanpa memahaminya menggunakan kereta kebal sebagai mesingan. Secara eksklusif mengikut hierarki pewarisan. Dan dia benar-benar betul, kerana orang yang merancang hierarki sedemikian membuat kesilapan.
Secara umum, saya tidak begitu memahami pendekatan " lebih mudah untuk saya dengan cara ini". Ia mudah untuk menulis seperti pendengar, dan mereka yang mengatakan tatabahasa asas adalah kazly. Sudah tentu, saya membesar-besarkan, tetapi idea utama kekal - sebagai tambahan kepada kemudahan seketika, terdapat perkara seperti celik huruf. Konsep ini ditakrifkan berdasarkan pengalaman orang yang sangat besar. Sebenarnya, inilah yang dalam bahasa Inggeris dipanggil "amalan terbaik" - penyelesaian terbaik. Dan lebih kerap daripada tidak, penyelesaian yang kelihatan lebih mudah membawa banyak masalah pada masa hadapan.
Contoh ini, sudah tentu, sangat dibesar-besarkan dan oleh itu tidak masuk akal. Walau bagaimanapun, terdapat kes yang kurang jelas yang membawa kepada akibat bencana. Dengan mewarisi daripada objek, bukannya mengagregatkannya, pembangun memberikan sesiapa sahaja keupayaan untuk menggunakan fungsi objek induk secara langsung. Dengan semua yang tersirat. Bayangkan anda mempunyai kelas yang berfungsi dengan pangkalan data, DBManager . Anda membuat kelas lain yang akan berfungsi dengan data anda menggunakan DBManager - DataManager . Kelas ini akan melaksanakan kawalan data, transformasi, tindakan tambahan, dsb. Secara umum, lapisan antara lapisan perniagaan dan lapisan asas. Jika anda mewarisi DataManager daripada DBManager, maka sesiapa yang menggunakannya akan mempunyai akses kepada pangkalan data secara langsung. Dan, oleh itu, dia akan dapat melakukan apa-apa tindakan yang memintas kawalan, transformasi, dsb. Okay, mari kita anggap bahawa tiada sesiapa yang mahu menyebabkan kemudaratan yang disengajakan dan tindakan langsung adalah cekap. Tetapi! Mari kita anggap bahawa asas telah berubah. Maksud saya, beberapa prinsip kawalan atau transformasi telah berubah. DataManager telah ditukar. Tetapi kod yang sebelum ini berfungsi secara langsung dengan pangkalan data akan terus berfungsi. Mereka kemungkinan besar tidak akan mengingatinya. Hasilnya ialah ralat kelas sedemikian sehingga mereka yang mencarinya akan bertukar menjadi kelabu. Ia tidak akan berlaku kepada sesiapa sahaja bahawa mereka bekerja dengan pangkalan data memintas DataManager. By the way, contoh dari kehidupan sebenar. Ia mengambil masa yang SANGAT lama untuk mencari ralat. Akhirnya, saya akan mengatakannya sekali lagi. Warisan HANYA boleh digunakan apabila terdapat hubungan "adalah". Kerana ini adalah intipati warisan - keupayaan untuk menggunakan objek kelas kanak-kanak sebagai objek kelas asas. Jika tiada hubungan "adalah" antara kelas, TIDAK HARUS ada warisan!!! Tidak pernah dan dalam apa jua keadaan. Dan lebih-lebih lagi - hanya kerana ia sangat mudah. Pautan ke sumber asal: http://www.skipy.ru/philosophy/inheritance.html
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION