JavaRush /Java blogi /Random-UZ /Sinflar va interfeyslarni loyihalash (maqolaning tarjimas...
fatesha
Daraja

Sinflar va interfeyslarni loyihalash (maqolaning tarjimasi)

Guruhda nashr etilgan
Sinflar va interfeyslarni loyihalash (Maqolaning tarjimasi) - 1

Tarkib

  1. Kirish
  2. Interfeyslar
  3. Interfeys belgilari
  4. Funktsional interfeyslar, statik usullar va standart usullar
  5. Abstrakt sinflar
  6. O'zgarmas (doimiy) sinflar
  7. Anonim sinflar
  8. Ko'rinish
  9. Meros olish
  10. Ko'p merosxo'rlik
  11. Meros va tarkibi
  12. Inkapsulyatsiya
  13. Yakuniy darslar va usullar
  14. Keyin nima
  15. Manba kodini yuklab oling

1.KIRISH

Qaysi dasturlash tilidan foydalanmasligingizdan qat'iy nazar (va Java ham bundan mustasno emas), yaxshi dizayn tamoyillariga rioya qilish toza, tushunarli va tekshirilishi mumkin bo'lgan kod yozishning kalitidir; va shuningdek, uni uzoq umr ko'rish va muammolarni hal qilishni osonlik bilan qo'llab-quvvatlash uchun yarating. Qo'llanmaning ushbu qismida biz Java tili taqdim etadigan asosiy qurilish bloklarini muhokama qilamiz va dizayn qarorlarini yaxshiroq qabul qilishingizga yordam berish uchun bir nechta dizayn tamoyillarini kiritamiz. Aniqroq qilib aytganda, biz standart usullardan foydalangan holda interfeys va interfeyslarni (Java 8-dagi yangi xususiyat), mavhum va yakuniy sinflar, o'zgarmas sinflar, meros, kompozitsiyani muhokama qilamiz va biz qisqacha to'xtalib o'tgan ko'rinish (yoki mavjudlik) qoidalarini qayta ko'rib chiqamiz. 1-qism dars "Qanday qilib ob'ektlarni yaratish va yo'q qilish" .

2. INTERFEYSLAR

Ob'ektga yo'naltirilgan dasturlashda interfeys tushunchasi shartnomalarni ishlab chiqish uchun asos bo'ladi . Xulosa qilib aytganda, interfeyslar bir qator usullarni (shartnomalarni) belgilaydi va ushbu interfeys uchun qo'llab-quvvatlashni talab qiladigan har bir sinf ushbu usullarni amalga oshirishni ta'minlashi kerak: juda oddiy, ammo kuchli g'oya. Ko'pgina dasturlash tillari u yoki bu shaklda interfeyslarga ega, ammo Java, xususan, buning uchun tilni qo'llab-quvvatlaydi. Keling, Java-da oddiy interfeys ta'rifini ko'rib chiqaylik.
package com.javacodegeeks.advanced.design;

public interface SimpleInterface {
void performAction();
}
Yuqoridagi parchada biz chaqirgan interfeys SimpleInterfacefaqat bitta usulni e'lon qiladi performAction. Interfeyslar va sinflar o'rtasidagi asosiy farq shundaki, interfeyslar kontakt nima bo'lishi kerakligini belgilaydi (ular usulni e'lon qiladi), lekin ularning amalga oshirilishini ta'minlamaydi. Biroq, Java-dagi interfeyslar murakkabroq bo'lishi mumkin: ular ichki interfeyslarni, sinflarni, hisoblashlarni, izohlarni va doimiylarni o'z ichiga olishi mumkin. Masalan:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefinitions {
    String CONSTANT = "CONSTANT";

    enum InnerEnum {
        E1, E2;
    }

    class InnerClass {
    }

    interface InnerInterface {
        void performInnerAction();
    }

    void performAction();
}
Ushbu murakkabroq misolda interfeyslar joylashtirish konstruksiyalari va metod deklaratsiyasiga so'zsiz qo'yadigan bir nechta cheklovlar mavjud va ular Java kompilyatori tomonidan amalga oshiriladi. Birinchidan, agar aniq e'lon qilinmagan bo'lsa ham, interfeysdagi har bir usul deklaratsiyasi ommaviydir ( va faqat ommaviy bo'lishi mumkin). Shunday qilib, quyidagi usul deklaratsiyasi ekvivalentdir:
public void performAction();
void performAction();
Shuni ta'kidlash kerakki, interfeysdagi har bir usul bevosita abstrakt deb e'lon qilinadi va hatto bu usul deklaratsiyasi ham ekvivalentdir:
public abstract void performAction();
public void performAction();
void performAction();
E'lon qilingan doimiy maydonlarga kelsak, ular ommaviy bo'lishdan tashqari , ular bilvosita statik va yakuniy deb belgilangan . Shuning uchun quyidagi deklaratsiyalar ham ekvivalentdir:
String CONSTANT = "CONSTANT";
public static final String CONSTANT = "CONSTANT";
Nihoyat, ichki o'rnatilgan sinflar, interfeyslar yoki hisoblar umumiy bo'lishdan tashqari , bilvosita statik deb e'lon qilinadi . Masalan, ushbu deklaratsiyalar ham quyidagilarga teng:
class InnerClass {
}

static class InnerClass {
}
Siz tanlagan uslub shaxsiy imtiyozdir, lekin interfeyslarning ushbu oddiy xususiyatlarini bilish sizni keraksiz yozishdan qutqarishi mumkin.

3. Interfeys belgisi

Marker interfeysi - bu usullar yoki boshqa ichki konstruktsiyalarga ega bo'lmagan interfeysning maxsus turi. Java kutubxonasi buni qanday belgilaydi:
public interface Cloneable {
}
Interfeys belgilari o'z-o'zidan shartnomalar emas, balki ba'zi bir o'ziga xos xususiyatni sinfga "biriktirish" yoki "bog'lash" uchun biroz foydali texnikadir. Misol uchun, Cloneable ga nisbatan sinf klonlanadigan sifatida belgilangan, ammo buni amalga oshirish mumkin yoki kerak bo'lgan usul interfeysning bir qismi emas. Interfeys belgisining yana bir mashhur va keng qo'llaniladigan misoli Serializable:
public interface Serializable {
}
Ushbu interfeys sinfni ketma-ketlashtirish va seriyadan chiqarish uchun mos deb belgilaydi va yana buni qanday amalga oshirish mumkinligini yoki amalga oshirilishini aniqlamaydi. Interfeys belgilarining ob'ektga yo'naltirilgan dasturlashda o'z o'rni bor, garchi ular shartnoma bo'lish interfeysining asosiy maqsadini qondirmasa ham. 

4. FUNKSIONAL INTERFEYSLAR, SOVVUTLI USULLAR VA STATIK USULLAR

Java 8 versiyasi chiqqandan beri interfeyslar juda qiziqarli yangi xususiyatlarga ega bo'ldi: statik usullar, standart usullar va lambdalardan avtomatik konvertatsiya qilish (funktsional interfeyslar). Interfeyslar bo'limida biz Java-dagi interfeyslar faqat usullarni e'lon qilishi mumkinligi, lekin ularni amalga oshirishni ta'minlamasligini ta'kidladik. Odatiy usul bilan narsalar boshqacha: interfeys standart kalit so'z bilan usulni belgilashi va uni amalga oshirishni ta'minlashi mumkin. Masalan:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefaultMethods {
    void performAction();

    default void performDefaulAction() {
        // Implementation here
    }
}
Namuna darajasida bo'lgani uchun standart usullar har bir interfeysni amalga oshirish orqali bekor qilinishi mumkin, lekin interfeyslar endi statik usullarni ham o'z ichiga olishi mumkin, masalan: com.javacodegeeks.advanced.design paketi;
public interface InterfaceWithDefaultMethods {
    static void createAction() {
        // Implementation here
    }
}
Aytish mumkinki, interfeysda amalga oshirishni ta'minlash shartnomani dasturlashning butun maqsadini yo'q qiladi. Ammo bu xususiyatlarning Java tiliga kiritilishining sabablari ko'p va ular qanchalik foydali yoki chalkash bo'lmasin, ular siz va sizning foydalanishingiz uchun mavjud. Funktsional interfeyslar butunlay boshqacha hikoya bo'lib, tilga juda foydali qo'shimchalar ekanligi isbotlangan. Asosan, funktsional interfeys - bu faqat bitta mavhum usul e'lon qilingan interfeys. RunnableStandart kutubxona interfeysi bu kontseptsiyaning juda yaxshi namunasidir.
@FunctionalInterface
public interface Runnable {
    void run();
}
Java kompilyatori funktsional interfeyslarga boshqacha munosabatda bo'ladi va lambda funktsiyasini mantiqiy bo'lgan joyda funktsional interfeysni amalga oshirishga aylantirishi mumkin. Keling, quyidagi funktsiya tavsifini ko'rib chiqaylik: 
public void runMe( final Runnable r ) {
    r.run();
}
Ushbu funktsiyani Java 7 va undan pastroq versiyalarda chaqirish uchun interfeysni amalga oshirish kerak Runnable(masalan, anonim sinflar yordamida), lekin Java 8 da lambda sintaksisi yordamida run() usulini amalga oshirishni ta'minlash kifoya:
runMe( () -> System.out.println( "Run!" ) );
Bundan tashqari, @FunctionalInterface izohi (izohlar darslikning 5-qismida batafsil yoritiladi) kompilyator interfeysda faqat bitta mavhum usul mavjudligini tekshirishi mumkinligiga ishora qiladi, shuning uchun kelajakda interfeysga kiritilgan har qanday o‘zgartirishlar bu taxminni buzmaydi. .

5. REFERAT DARSLAR

Java tili tomonidan qo'llab-quvvatlanadigan yana bir qiziqarli tushuncha - bu mavhum sinflar tushunchasi. Mavhum sinflar Java 7 interfeyslariga biroz o'xshaydi va Java 8 da standart usul interfeysiga juda yaqin. Oddiy sinflardan farqli o'laroq, mavhum sinfni yaratib bo'lmaydi, lekin uni quyi sinflarga ajratish mumkin (batafsilroq ma'lumot uchun Meros bo'limiga qarang). Eng muhimi, mavhum sinflar mavhum usullarni o'z ichiga olishi mumkin: interfeys kabi amalga oshirilmaydigan maxsus usul. Masalan:
package com.javacodegeeks.advanced.design;

public abstract class SimpleAbstractClass {
    public void performAction() {
        // Implementation here
    }

    public abstract void performAnotherAction();
}
Ushbu misolda sinf mavhumSimpleAbstractClass deb e'lon qilingan va bitta e'lon qilingan mavhum usulni o'z ichiga oladi. Mavhum sinflar juda foydali; amalga oshirish tafsilotlarining ko'p qismi yoki hatto ba'zi qismlari ko'plab kichik sinflar o'rtasida taqsimlanishi mumkin. Qanday bo'lmasin, ular hali ham eshikni ochiq qoldiradilar va mavhum usullardan foydalangan holda har bir kichik sinfga xos bo'lgan xatti-harakatlarni sozlash imkonini beradi. Shuni ta'kidlash kerakki, faqat ommaviy deklaratsiyalarni o'z ichiga olishi mumkin bo'lgan interfeyslardan farqli o'laroq, mavhum sinflar mavhum usulning ko'rinishini nazorat qilish uchun mavjudlik qoidalarining to'liq kuchidan foydalanishi mumkin.

6. TEZKOR DARSLAR

Hozirgi vaqtda dasturiy ta'minotni ishlab chiqishda o'zgarmaslik tobora muhim ahamiyat kasb etmoqda. Ko'p yadroli tizimlarning o'sishi ma'lumotlar almashish va parallelizm bilan bog'liq ko'plab muammolarni keltirib chiqardi. Ammo bitta muammo aniq paydo bo'ldi: oz (yoki hatto yo'q) o'zgaruvchan holatga ega bo'lish yaxshi kengayishga (miqyosda) va tizim haqida oson fikr yuritishga olib keladi. Afsuski, Java tili sinfning o'zgarmasligini munosib qo'llab-quvvatlamaydi. Biroq, texnikalar kombinatsiyasidan foydalangan holda, o'zgarmas sinflarni loyihalash mumkin bo'ladi. Birinchidan, sinfning barcha maydonlari yakuniy bo'lishi kerak ( yakuniy deb belgilangan ). Bu yaxshi boshlanish, ammo bu kafolat emas. 
package com.javacodegeeks.advanced.design;

import java.util.Collection;

public class ImmutableClass {
    private final long id;
    private final String[] arrayOfStrings;
    private final Collection<String> collectionOfString;
}
Ikkinchidan, to'g'ri ishga tushirishni ta'minlang: agar maydon to'plam yoki massivga havola bo'lsa, bu maydonlarni to'g'ridan-to'g'ri konstruktor argumentlaridan tayinlamang, uning o'rniga nusxa oling. Bu to'plam yoki massiv holati undan tashqarida o'zgartirilmasligini ta'minlaydi.
public ImmutableClass( final long id, final String[] arrayOfStrings,
        final Collection<String> collectionOfString) {
    this.id = id;
    this.arrayOfStrings = Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
    this.collectionOfString = new ArrayList<>( collectionOfString );
}
Va nihoyat, to'g'ri kirishni ta'minlash (oluvchilar). To'plamlar uchun o'zgarmaslik o'ram sifatida taqdim etilishi kerak  Collections.unmodifiableXxx: Massivlar bilan haqiqiy o'zgarmaslikni ta'minlashning yagona yo'li massivga havolani qaytarish o'rniga nusxasini taqdim etishdir. Bu amaliy nuqtai nazardan qabul qilinishi mumkin emas, chunki u massivning o'lchamiga juda bog'liq va axlat yig'uvchiga katta bosim o'tkazishi mumkin.
public String[] getArrayOfStrings() {
    return Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
}
Hatto bu kichik misol ham Javada o'zgarmaslik hali birinchi darajali fuqaro emasligi haqida yaxshi fikr beradi. Agar o'zgarmas sinf boshqa sinf ob'ektiga tegishli maydonga ega bo'lsa, ishlar murakkablashishi mumkin. Bu sinflar ham o'zgarmas bo'lishi kerak, ammo buni ta'minlashning hech qanday usuli yo'q. FindBugs va PMD kabi bir nechta munosib Java manba kodi analizatorlari mavjud bo'lib, ular kodingizni tekshirish va umumiy Java dasturlash kamchiliklarini ko'rsatish orqali katta yordam beradi. Ushbu vositalar har qanday Java dasturchisining ajoyib do'stlaridir.

7. ANONIM SINFLAR

Java 8-dan oldingi davrda anonim sinflar sinflarning tezda aniqlanishi va darhol yaratilishini ta'minlashning yagona yo'li edi. Anonim sinflarning maqsadi qozonlarni kamaytirish va sinflarni rekord sifatida taqdim etishning qisqa va oson usulini taqdim etish edi. Keling, Java-da yangi ipni yaratishning odatiy eski usulini ko'rib chiqaylik:
package com.javacodegeeks.advanced.design;

public class AnonymousClass {
    public static void main( String[] args ) {
        new Thread(
            // Example of creating anonymous class which implements
            // Runnable interface
            new Runnable() {
                @Override
                public void run() {
                    // Implementation here
                }
            }
        ).start();
    }
}
Ushbu misolda interfeysni amalga oshirish Runnabledarhol anonim sinf sifatida taqdim etiladi. Anonim sinflar bilan bog'liq ba'zi cheklovlar mavjud bo'lsa-da, ulardan foydalanishning asosiy kamchiliklari Java tili sifatida majburiy bo'lgan juda batafsil konstruktsiya sintaksisidir. Hatto hech narsa qilmaydigan anonim sinf ham har yozilayotganda kamida 5 qator kod talab qiladi.
new Runnable() {
   @Override
   public void run() {
   }
}
Yaxshiyamki, Java 8, lambda va funktsional interfeyslar bilan bu stereotiplarning barchasi tezda yo'q bo'lib ketadi va nihoyat Java kodini yozish haqiqatan ham ixcham ko'rinadi.
package com.javacodegeeks.advanced.design;

public class AnonymousClass {
    public static void main( String[] args ) {
        new Thread( () -> { /* Implementation here */ } ).start();
    }
}

8. KO'RILISH

Biz allaqachon o'quv qo'llanmaning 1-qismida Java-da ko'rish va foydalanish qoidalari haqida bir oz gaplashdik. Ushbu bo'limda biz ushbu mavzuni yana bir bor ko'rib chiqamiz, lekin pastki sinflar kontekstida. Sinflar va interfeyslarni loyihalash (Maqolaning tarjimasi) - 2Turli darajadagi ko‘rinish sinflarga boshqa sinflar yoki interfeyslarni (masalan, agar ular turli paketlarda yoki bir-birining ichiga o‘rnatilgan bo‘lsa) yoki kichik sinflarga ota-onalarining usullari, konstruktorlari va maydonlarini ko‘rish va ularga kirish imkonini beradi yoki oldini oladi. Keyingi bo'limda, meros, biz buni amalda ko'ramiz.

9. MEROS

Meros ob'ektga yo'naltirilgan dasturlashning asosiy tushunchalaridan biri bo'lib, munosabatlar sinfini qurish uchun asos bo'lib xizmat qiladi. Koʻrinish va foydalanish imkoniyati qoidalari bilan birlashgan holda, meros sinflarni kengaytirilishi va saqlanishi mumkin boʻlgan ierarxiyaga aylantirish imkonini beradi. Kontseptual darajada Java-da meros subklassing va kengaytirilgan kalit so'z yordamida ota-klass bilan birga amalga oshiriladi. Subklass ota-sinfning barcha ochiq va himoyalangan elementlarini meros qilib oladi. Bunga qo'shimcha ravishda, agar ikkala (subklass va sinf) bir xil paketda bo'lsa, pastki sinf o'zining ota-klassining shaxsiy paketli elementlarini meros qilib oladi. Aytish joizki, siz nimani loyihalashtirmoqchi bo'lishingizdan qat'i nazar, sinf ommaga yoki uning kichik sinflariga taqdim etadigan minimal usullar to'plamiga rioya qilish juda muhimdir. Masalan, ko'rinish darajasi va ularning ta'siridagi farqni ko'rsatish uchun sinf Parentva uning pastki sinfini ko'rib chiqamiz .Child
package com.javacodegeeks.advanced.design;

public class Parent {
    // Everyone can see it
    public static final String CONSTANT = "Constant";

    // No one can access it
    private String privateField;
    // Only subclasses can access it
    protected String protectedField;

    // No one can see it
    private class PrivateClass {
    }

    // Only visible to subclasses
    protected interface ProtectedInterface {
    }

    // Everyone can call it
    public void publicAction() {
    }

    // Only subclass can call it
    protected void protectedAction() {
    }

    // No one can call it
    private void privateAction() {
    }

    // Only subclasses in the same package can call it
    void packageAction() {
    }
}
package com.javacodegeeks.advanced.design;

// Resides in the same package as parent class
public class Child extends Parent implements Parent.ProtectedInterface {
    @Override
    protected void protectedAction() {
        // Calls parent's method implementation
        super.protectedAction();
    }

    @Override
    void packageAction() {
        // Do nothing, no call to parent's method implementation
    }

    public void childAction() {
        this.protectedField = "value";
    }
}
Merosning o'zi juda katta mavzu bo'lib, Java-ga xos bo'lgan juda ko'p nozik tafsilotlarga ega. Biroq, amal qilish oson bo'lgan bir nechta qoidalar mavjud va sinf ierarxiyasining qisqaligini saqlab qolish uchun uzoq yo'lni bosib o'tishi mumkin. Java-da, har bir kichik sinf, agar u yakuniy deb e'lon qilinmagan bo'lsa, o'z ota-onasining har qanday meros usullarini bekor qilishi mumkin. Biroq, usulni bekor qilingan deb belgilash uchun maxsus sintaksis yoki kalit so'z yo'q, bu chalkashlikka olib kelishi mumkin. Shuning uchun @Override izohi joriy etildi : agar sizning maqsadingiz meros qilib olingan usulni bekor qilish bo'lsa, uni qisqacha ko'rsatish uchun @Override izohidan foydalaning. Java dasturchilari dizaynda doimo duch keladigan yana bir dilemma bu interfeyslarni amalga oshirishga nisbatan sinf ierarxiyasini (aniq yoki mavhum sinflar bilan) qurishdir. Imkon qadar sinflar yoki abstrakt sinflarga nisbatan interfeyslarni afzal ko'rishni qat'iy tavsiya qilamiz. Interfeyslar engilroq, sinovdan o'tkazish va texnik xizmat ko'rsatish osonroq, shuningdek, amalga oshirish o'zgarishlarining nojo'ya ta'sirini kamaytiradi. Java standart kutubxonasida proksi-sinflarni yaratish kabi ko'plab ilg'or dasturlash usullari asosan interfeyslarga tayanadi.

10. KO'P KO'P MEROSLIK

C++ va boshqa ba'zi tillardan farqli o'laroq, Java bir nechta merosni qo'llab-quvvatlamaydi: Java-da har bir sinf faqat bitta to'g'ridan-to'g'ri ota-onaga ega bo'lishi mumkin (sinf Objectierarxiyaning yuqori qismida joylashgan). Biroq, sinf bir nechta interfeyslarni amalga oshirishi mumkin va shuning uchun interfeysni stacking Java-da bir nechta merosga erishishning (yoki simulyatsiya qilishning) yagona usuli hisoblanadi.
package com.javacodegeeks.advanced.design;

public class MultipleInterfaces implements Runnable, AutoCloseable {
    @Override
    public void run() {
        // Some implementation here
    }

    @Override
    public void close() throws Exception {
       // Some implementation here
    }
}
Bir nechta interfeyslarni amalga oshirish juda kuchli, lekin ko'pincha amalga oshirishdan qayta-qayta foydalanish zarurati Java-ning bir nechta merosni qo'llab-quvvatlamasligini bartaraf etish usuli sifatida chuqur sinf ierarxiyasiga olib keladi. 
public class A implements Runnable {
    @Override
    public void run() {
        // Some implementation here
    }
}
// Class B wants to inherit the implementation of run() method from class A.
public class B extends A implements AutoCloseable {
    @Override
    public void close() throws Exception {
       // Some implementation here
    }
}
// Class C wants to inherit the implementation of run() method from class A
// and the implementation of close() method from class B.
public class C extends B implements Readable {
    @Override
    public int read(java.nio.CharBuffer cb) throws IOException {
       // Some implementation here
    }
}
Va shunga o'xshash ... Java 8 ning yaqinda chiqarilishi standart usulni kiritish bilan bog'liq muammoni biroz hal qiladi. Standart usullar tufayli interfeyslar aslida nafaqat shartnomani, balki amalga oshirishni ham ta'minlaydi. Shu sababli, ushbu interfeyslarni amalga oshiradigan sinflar ham ushbu amalga oshirilgan usullarni avtomatik ravishda meros qilib oladi. Masalan:
package com.javacodegeeks.advanced.design;

public interface DefaultMethods extends Runnable, AutoCloseable {
    @Override
    default void run() {
        // Some implementation here
    }

    @Override
    default void close() throws Exception {
       // Some implementation here
    }
}

// Class C inherits the implementation of run() and close() methods from the
// DefaultMethods interface.
public class C implements DefaultMethods, Readable {
    @Override
    public int read(java.nio.CharBuffer cb) throws IOException {
       // Some implementation here
    }
}
Shuni yodda tutingki, bir nechta meros juda kuchli, ammo ayni paytda xavfli vositadir. Taniqli "O'lim olmosi" muammosi ko'pincha bir nechta merosni amalga oshirishdagi asosiy kamchilik sifatida tilga olinadi, bu esa ishlab chiquvchilarni sinf ierarxiyasini juda ehtiyotkorlik bilan loyihalashga majbur qiladi. Afsuski, standart usullarga ega Java 8 interfeyslari ham ushbu nuqsonlarning qurboni bo'ladi.
interface A {
    default void performAction() {
    }
}

interface B extends A {
    @Override
    default void performAction() {
    }
}

interface C extends A {
    @Override
    default void performAction() {
    }
}
Masalan, quyidagi kod parchasi kompilyatsiya qilinmaydi:
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
Shu oʻrinda shuni aytish joizki, Java tili sifatida har doim obʼyektga yoʻnaltirilgan dasturlashning burchak holatlaridan qochishga harakat qilgan, ammo til rivojlanib borgan sari bu holatlarning baʼzilari birdan paydo boʻla boshlagan. 

11. MEROS VA TARKIBI

Yaxshiyamki, meros sizning sinfingizni loyihalashning yagona usuli emas. Ko'pgina ishlab chiquvchilar merosdan ko'ra yaxshiroq deb hisoblaydigan yana bir muqobil kompozitsiyadir. G'oya juda oddiy: sinflar ierarxiyasini yaratish o'rniga ular boshqa sinflardan iborat bo'lishi kerak. Keling, ushbu misolni ko'rib chiqaylik:
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
Sinf Vehicledvigatel va g'ildiraklardan iborat (shuningdek, soddaligi uchun chetga qo'yilgan boshqa ko'plab qismlar). Biroq, aytish mumkinki, sinf Vehicleham dvigateldir, shuning uchun uni meros yordamida loyihalash mumkin. 
public class Vehicle extends Engine {
    private Wheels[] wheels;
    // ...
}
Qaysi dizayn yechimi to'g'ri bo'ladi? Umumiy asosiy ko'rsatmalar IS-A (is) va HAS-A (o'z ichiga oladi) tamoyillari sifatida tanilgan. IS-A - bu meros munosabatlari: pastki sinf ota-sinfning sinf spetsifikatsiyasini va ota-sinfning o'zgarishini ham qondiradi. subsinf) o'zining ota-onasini kengaytiradi. Agar bir ob'ekt boshqasini kengaytiradimi yoki yo'qligini bilmoqchi bo'lsangiz, moslik testini bajaring - IS -A (is).") Shuning uchun, HAS-A kompozitsion munosabatdir: sinf ob'ektga ega (yoki o'z ichiga oladi) ko'p hollarda HAS-A printsipi bir qator sabablarga ko'ra IS-A dan yaxshiroq ishlaydi: 
  • Dizayn yanada moslashuvchan;
  • Model yanada barqaror, chunki o'zgarishlar sinf ierarxiyasi bo'ylab tarqalmaydi;
  • Sinf va uning tarkibi ota-ona va uning kichik sinfini mahkam bog'laydigan kompozitsiyaga nisbatan erkin bog'langan.
  • Sinfdagi mantiqiy fikrlash jarayoni soddaroq, chunki uning barcha bog'liqliklari unga bir joyda kiritilgan. 
Nima bo'lishidan qat'iy nazar, merosning o'z o'rni bor va bir qator mavjud dizayn muammolarini turli yo'llar bilan hal qiladi, shuning uchun uni e'tiborsiz qoldirmaslik kerak. Ob'ektga yo'naltirilgan modelingizni loyihalashda ushbu ikki muqobilni yodda tuting.

12. KAPSULYASIYA.

Ob'ektga yo'naltirilgan dasturlashda inkapsulyatsiya tushunchasi barcha amalga oshirish tafsilotlarini (masalan, ish rejimi, ichki usullar va boshqalar) tashqi dunyodan yashirishdir. Inkapsulyatsiyaning afzalliklari - barqarorlik va o'zgartirish qulayligi. Sinfning ichki amalga oshirilishi yashirin, sinf ma'lumotlari bilan ishlash faqat sinfning ommaviy usullari orqali amalga oshiriladi (agar siz ko'p odamlar tomonidan ishlatiladigan kutubxona yoki ramka ishlab chiqayotgan bo'lsangiz, haqiqiy muammo). Java-da inkapsulyatsiya ko'rinish va foydalanish qoidalari orqali amalga oshiriladi. Java-da maydonlarni hech qachon to'g'ridan-to'g'ri ko'rsatmaslik eng yaxshi amaliyot hisoblanadi, faqat qabul qiluvchilar va sozlagichlar orqali (agar maydonlar yakuniy belgilanmagan bo'lsa). Masalan:
package com.javacodegeeks.advanced.design;

public class Encapsulation {
    private final String email;
    private String address;

    public Encapsulation( final String email ) {
        this.email = email;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getEmail() {
        return email;
    }
}
Ushbu misol Java tilida JavaBeans deb ataladigan narsani eslatadi : standart Java sinflari konventsiyalar to'plamiga muvofiq yoziladi, ulardan biri maydonlarga faqat getter va setter usullari yordamida kirish imkonini beradi. Meros bo'limida ta'kidlaganimizdek, inkapsulyatsiya tamoyillaridan foydalangan holda har doim sinfdagi minimal reklama shartnomasiga rioya qiling. Ommaviy bo'lmasligi kerak bo'lgan hamma narsa shaxsiy bo'lishi kerak (yoki siz hal qilayotgan muammoga qarab himoyalangan/xususiy paket). Bu sizga o'zgarishlarsiz (yoki hech bo'lmaganda minimallashtirish) dizayn erkinligini berish orqali uzoq muddatda o'z samarasini beradi. 

13. Yakuniy darslar va metodlar

Java-da sinfning boshqa sinfning pastki sinfiga aylanishini oldini olishning bir usuli bor: boshqa sinf yakuniy deb e'lon qilinishi kerak. 
package com.javacodegeeks.advanced.design;

public final class FinalClass {
}
Usul deklaratsiyasidagi  bir xil yakuniy kalit so'z pastki sinflarning usulni bekor qilishiga yo'l qo'ymaydi.
package com.javacodegeeks.advanced.design;

public class FinalMethod {
    public final void performAction() {
    }
}
Sinf yoki usullar yakuniy yoki yakuniy bo'lmasligini hal qilish uchun umumiy qoidalar yo'q. Yakuniy sinflar va usullar kengayishni cheklaydi va sinfni meros qilib olish kerakmi yoki yo'qmi yoki kelajakda usulni bekor qilish kerakmi yoki yo'qmi, oldindan o'ylash juda qiyin. Bu kutubxona ishlab chiquvchilari uchun ayniqsa muhimdir, chunki bunday dizayn qarorlari kutubxonaning qo'llanilishini sezilarli darajada cheklashi mumkin. Java standart kutubxonasida yakuniy sinflarning bir nechta namunalari mavjud, ulardan eng mashhuri String sinfidir. Dastlabki bosqichda bu qaror ishlab chiquvchilarning stringni amalga oshirish bo'yicha o'zlarining "yaxshiroq" echimini topishga urinishlarining oldini olish uchun qabul qilingan. 

14. KEYINGI NIMA

Darsning ushbu qismida biz Java tilida ob'ektga yo'naltirilgan dasturlash tushunchalarini ko'rib chiqdik. Biz, shuningdek, kontrakt dasturlarini tez ko'rib chiqdik, ba'zi funktsional tushunchalarga to'xtalib, vaqt o'tishi bilan til qanday rivojlanganligini ko'rib chiqdik. Darsning keyingi qismida biz generiklar va ular dasturlashda xavfsizlik turiga yondashuvimizni qanday o'zgartirishi bilan tanishamiz. 

15. MANBA KODNI YUKLAB OLISH

Manbani bu yerdan yuklab olishingiz mumkin - advanced-java-part-3 Manba: Qanday qilib sinflarni loyihalash va
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION