JavaRush /Java блогу /Random-KY /Класстарды жана интерфейстерди долбоорлоо (макаланын кото...
fatesha
Деңгээл

Класстарды жана интерфейстерди долбоорлоо (макаланын котормосу)

Группада жарыяланган
Класстарды жана интерфейстерди долбоорлоо (макаланын котормосу) - 1

Мазмун

  1. Киришүү
  2. Interfaces
  3. Интерфейс маркерлери
  4. Функционалдык интерфейстер, статикалык методдор жана демейки методдор
  5. Абстракттуу класстар
  6. Өзгөрбөс (туруктуу) класстар
  7. Анонимдүү класстар
  8. Көрүнүү
  9. Мурас
  10. Көптөгөн мурас
  11. Мурас жана курамы
  12. Инкапсуляция
  13. Жыйынтыктоочу класстар жана методдор
  14. Кийинкиси эмне
  15. Булак codeун жүктөп алыңыз

1. КИРИШҮҮ

Кайсы программалоо тorн колдонбоңуз (жана Java да өзгөчө эмес), жакшы дизайн принциптерин сактоо таза, түшүнүктүү жана текшерилүүчү code жазуунун ачкычы болуп саналат; жана ошондой эле аны узак мөөнөттүү жана көйгөйдү чечүүнү оңой колдоо үчүн түзүңүз. Окуу куралынын бул бөлүгүндө биз Java тor камсыз кылган негизги курулуш блокторун талкуулайбыз жана жакшыраак дизайн чечимдерин кабыл алууга жардам берүү үчүн бир нече дизайн принциптерин киргизебиз. Тагыраак айтканда, биз интерфейстерди жана интерфейстерди демейки ыкмаларды (Java 8деги жаңы функция), абстракттуу жана жыйынтыктоочу класстарды, өзгөрүлбөс класстарды, мурас, композицияны талкуулайбыз жана биз кыскача сөз кылган көрүнүү (же жеткorктүүлүк) эрежелерин кайра карап чыгабыз. 1-бөлүк сабак "Объекттерди кантип түзүү жана жок кылуу керек" .

2. ИНТЕРФЕЙСТЕР

Объектке багытталган программалоодо интерфейстердин түшүнүгү келишимдерди иштеп чыгуу үчүн негиз болуп саналат . Кыскача айтканда, интерфейстер методдордун (контракттардын) топтомун аныктайт жана ошол конкреттүү интерфейс үчүн колдоону талап кылган ар бир класс ошол методдордун ишке ашырылышын камсыз кылышы керек: кыйла жөнөкөй, бирок күчтүү идея. Көптөгөн программалоо тилдеринде тигил же бул формада интерфейстер бар, бирок өзгөчө Java бул үчүн тилдик колдоо көрсөтөт. Келгиле, Javaдагы жөнөкөй интерфейстин аныктамасын карап көрөлү.
package com.javacodegeeks.advanced.design;

public interface SimpleInterface {
void performAction();
}
Жогорудагы үзүндүдө, биз чакырган интерфейс SimpleInterface, деп аталган бир гана ыкманы жарыялайт performAction. Интерфейстердин класстардын негизги айырмасы - интерфейстер байланыш кандай болушу керек экенин көрсөтүп турат (алар методду жарыялашат), бирок алардын аткарылышын камсыз кылbyte. Бирок, Javaдагы интерфейстер татаалыраак болушу мүмкүн: алар уяланган интерфейстерди, класстарды, эсептерди, annotationларды жана константаларды камтышы мүмкүн. Мисалы:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefinitions {
    String CONSTANT = "CONSTANT";

    enum InnerEnum {
        E1, E2;
    }

    class InnerClass {
    }

    interface InnerInterface {
        void performInnerAction();
    }

    void performAction();
}
Бул татаал мисалда, интерфейстер уя курууларга жана метод декларацияларына шартсыз таңуулаган бир нече чектөөлөр бар жана алар Java компилятору тарабынан аткарылат. Биринчиден, ачык жарыяланбаса да, интерфейстеги ар бир метод декларациясы жалпыга ачык (жана ачык гана болушу мүмкүн). Ошентип, төмөнкү ыкма декларациялары эквиваленттүү:
public void performAction();
void performAction();
Белгилей кетчү нерсе, интерфейстеги ар бир метод абстракттуу деп жарыяланып , жада калса бул ыкма декларациялары эквиваленттүү:
public abstract void performAction();
public void performAction();
void performAction();
Жарыяланган туруктуу талааларга келсек, алар жалпыга ачык болуудан тышкары , ошондой эле кыйыр түрдө статикалык жана акыркы деп белгиленген . Демек, төмөнкү декларациялар да эквиваленттүү:
String CONSTANT = "CONSTANT";
public static final String CONSTANT = "CONSTANT";
Акырында, уяланган класстар, интерфейстер же эсептер, жалпыга ачык болуу менен бирге , ошондой эле кыйыр түрдө static деп жарыяланат . Мисалы, бул декларациялар да төмөнкүлөргө барабар:
class InnerClass {
}

static class InnerClass {
}
Сиз тандаган стиль жеке каалооңуз, бирок интерфейстердин бул жөнөкөй касиеттерин билүү сизди керексиз терүүдөн сактайт.

3. Интерфейс маркери

Маркер интерфейси - бул методдору же башка уя курулган конструкциялары жок интерфейстин өзгөчө түрү. Java китепканасы аны кантип аныктайт:
public interface Cloneable {
}
Интерфейс маркерлери өз алдынча келишим эмес, бирок класска кандайдыр бир өзгөчөлүктөрдү "тиркештирүү" же "байланыштыруу" үчүн кандайдыр бир пайдалуу ыкма болуп саналат. Мисалы, Cloneable ге карата класс клондоочу катары белгиленет, бирок муну ишке ашыруу жолу интерфейстин бир бөлүгү эмес. Интерфейс маркеринин дагы бир белгилүү жана кеңири колдонулган мисалы Serializable:
public interface Serializable {
}
Бул интерфейс классты сериялаштыруу жана сериялаштыруу үчүн ылайыктуу деп белгилейт жана дагы бир жолу, муну кантип ишке ашырууга болорун же керектиги көрсөтүлгөн эмес. Интерфейс маркерлери an objectиге багытталган программалоодо өз ордун ээлейт, бирок алар интерфейстин негизги максатын контракт катары канааттандырbyte. 

4. ФУНКЦИОНАЛДЫК ИНТЕРФЕЙСТЕР, ДЕПУТАТТЫК МЕТОДДОР ЖАНА СТАТИКАЛЫК МЕТООДдор

Java 8 чыгарылгандан бери интерфейстер абдан кызыктуу жаңы өзгөчөлүктөргө ээ болду: статикалык ыкмалар, демейки ыкмалар жана ламбдалардан автоматтык түрдө конвертациялоо (функционалдык интерфейстер). Интерфейстер бөлүмүндө биз Javaдагы интерфейстер методдорду гана жарыялай аларын, бирок аларды ишке ашырууну камсыз кылбагандыгын баса белгиледик. Демейки ыкма менен баары башкача болот: интерфейс демейки ачкыч сөз менен ыкманы белгилеп , аны ишке ашырууну камсыздай алат. Мисалы:
package com.javacodegeeks.advanced.design;

public interface InterfaceWithDefaultMethods {
    void performAction();

    default void performDefaulAction() {
        // Implementation here
    }
}
Инстанция деңгээлинде болгондуктан, демейки ыкмалар ар бир интерфейсти ишке ашыруу аркылуу жокко чыгарылышы мүмкүн, бирок интерфейстер эми статикалык ыкмаларды да камтышы мүмкүн, мисалы: com.javacodegeeks.advanced.design пакети;
public interface InterfaceWithDefaultMethods {
    static void createAction() {
        // Implementation here
    }
}
Интерфейсте ишке ашырууну камсыздоо келишимдик программалоонун бүт максатын жокко чыгарат деп айтууга болот. Бирок бул функциялардын Java тorне киргизилгенинин көптөгөн себептери бар жана алар канчалык пайдалуу же чаташкан болсо да, алар сиз үчүн жана колдонууңуз үчүн бар. Функционалдык интерфейстер таптакыр башка окуя жана тилге абдан пайдалуу толуктоолор экени далилденген. Негизинен функционалдык интерфейс – бул бир гана абстракттуу методу бар интерфейс. RunnableСтандарттык китепкана интерфейси бул түшүнүктүн абдан жакшы мисалы болуп саналат.
@FunctionalInterface
public interface Runnable {
    void run();
}
Java компилятору функционалдык интерфейстерге башкача мамиле кылат жана lambda функциясын функционалдык интерфейсти ишке ашырууга айландырышы мүмкүн. Төмөнкү функциянын сүрөттөмөсүн карап көрөлү: 
public void runMe( final Runnable r ) {
    r.run();
}
Бул функцияны Java 7 жана андан төмөн тилдерде чакыруу үчүн интерфейстин ишке ашырылышы камсыз кылынышы керек Runnable(мисалы, анонимдүү класстарды колдонуу менен), бирок Java 8де lambda синтаксисин колдонуу менен run() ыкмасын ишке ашырууну камсыз кылуу жетиштүү:
runMe( () -> System.out.println( "Run!" ) );
Кошумчалай кетсек, @FunctionalInterface annotationсы (annotationлар окуу куралынын 5-бөлүгүндө кеңири каралат) компилятор интерфейсте бир гана абстракттуу методду камтыганын текшере аларын ишара кылат, андыктан келечекте интерфейске киргизилген бардык өзгөртүүлөр бул божомолду бузbyte. .

5. РЕФЕРАТ САБАКТАР

Java тor тарабынан колдоого алынган дагы бир кызыктуу түшүнүк абстракттуу класстар түшүнүгү болуп саналат. Абстракттуу класстар Java 7деги интерфейстерге бир аз окшош жана Java 8деги демейки метод интерфейсине абдан жакын. Кадимки класстардан айырмаланып, абстракттуу классты түзүү мүмкүн эмес, бирок аны субкласска бөлүүгө болот (кеңири маалымат үчүн Мурас бөлүмүн караңыз). Андан да маанилүүсү, абстракттуу класстар абстракттуу методдорду камтышы мүмкүн: интерфейс сыяктуу ишке ашыруусуз методдун өзгөчө түрү. Мисалы:
package com.javacodegeeks.advanced.design;

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

    public abstract void performAnotherAction();
}
Бул мисалда класс абстракттууSimpleAbstractClass деп жарыяланып , бир жарыяланган абстракттуу ыкманы камтыйт. Абстракттуу класстар абдан пайдалуу; ишке ашыруунун деталдарынын көбү же кээ бир бөлүктөрү көптөгөн субкласстардын арасында бөлүштүрүлүшү мүмкүн. Кандай болбосун, алар дагы эле эшикти ачык калтырышат жана абстрактуу ыкмаларды колдонуу менен ар бир подкласска мүнөздүү жүрүм-турумду ыңгайлаштырууга мүмкүнчүлүк берет. Белгилей кетчү нерсе, ачык декларацияларды гана камтышы мүмкүн болгон интерфейстерден айырмаланып, абстракттуу класстар абстракттуу методдун көрүнүшүн көзөмөлдөө үчүн жеткorктүүлүк эрежелеринин толук күчүн колдоно алышат.

6. ТЕЗ

Азыркы учурда программалык камсыздоону иштеп чыгууда өзгөрбөстүк барган сайын маанилүү болуп баратат. Көп ядролуу системалардын өсүшү маалымат алмашууга жана параллелизмге байланыштуу көптөгөн маселелерди көтөрдү. Бирок, албетте, бир көйгөй пайда болду: өзгөрүлүүчү абалдын аз болушу (же болбосо да жок) системанын кеңейүүсүнө (масштабдуулугуна) жана жеңил ой жүгүртүүгө алып келет. Тилекке каршы, Java тor класстын өзгөрбөстүгү үчүн татыктуу колдоо көрсөтө алbyte. Бирок, ыкмаларды айкалыштыруу менен, өзгөрүлгүс класстарды долбоорлоо мүмкүн болот. Биринчиден, класстын бардык талаалары акыркы болушу керек ( акыркы деп белгиленген ). Бул жакшы башталыш, бирок кепилдик жок. 
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;
}
Экинчиден, туура инициализацияны камсыз кылыңыз: эгерде талаа коллекцияга же массивге шилтеме болсо, ал талааларды түз конструктор аргументтеринен дайындабаңыз, анын ордуна көчүрмөлөрдү жасаңыз. Бул коллекциянын же массивдин абалы анын сыртында өзгөртүлбөсүн камсыздайт.
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 );
}
Акыр-аягы, туура жеткorктүүлүгүн камсыз кылуу (алуучу). Коллекциялар үчүн өзгөрбөстүктү орогуч катары берүү керек  Collections.unmodifiableXxx: Массивдер менен чыныгы өзгөрбөстүктү камсыз кылуунун жалгыз жолу массивге шилтемени кайтаруунун ордуна көчүрмөнү берүү болуп саналат. Бул практикалык көз карашта кабыл алынбашы мүмкүн, анткени ал массивдин өлчөмүнө абдан көз каранды жана таштанды жыйноочуга чоң басым жасайт.
public String[] getArrayOfStrings() {
    return Arrays.copyOf( arrayOfStrings, arrayOfStrings.length );
}
Бул кичинекей мисал да өзгөрүлгүс али Javaдагы биринчи класстын жараны эмес экенин жакшы түшүнүк берет. Эгерде өзгөрүлбөс класста башка класстын an objectисине тиешелүү талаа бар болсо, иштер татаалдашы мүмкүн. Бул класстар да өзгөрүлгүс болушу керек, бирок муну камсыз кылуунун эч кандай жолу жок. FindBugs жана PMD сыяктуу бир нече татыктуу Java булак codeу анализаторлору бар, алар сиздин codeуңузду текшерип, жалпы Java программалоо кемчorктерин көрсөтүү менен жардам берет. Бул куралдар ар бир Java иштеп чыгуучунун мыкты достору.

7. АНОНИМ КЛАССТАР

Java 8ге чейинки доордо анонимдүү класстар класстарды тез арада аныктап, дароо түзүүнү камсыз кылуунун жалгыз жолу болгон. Анонимдүү класстардын максаты класстарды рекорд катары көрсөтүүнүн кыска жана оңой жолун камсыз кылуу болгон. Келгиле, Java тorнде жаңы жипти чыгаруунун типтүү эски ыкмасын карап көрөлү:
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();
    }
}
Бул мисалда Runnableинтерфейстин ишке ашырылышы анонимдүү класс катары дароо берилет. Анонимдүү класстар менен байланышкан кээ бир чектөөлөр бар болсо да, аларды колдонуунун негизги кемчorктери Java тил катары милдеттүү болгон өтө кылдат конструкция синтаксиси болуп саналат. Жада калса эч нерсе кылбаган анонимдүү класс ар бир жазылган сайын кеминде 5 сап codeду талап кылат.
new Runnable() {
   @Override
   public void run() {
   }
}
Бактыга жараша, Java 8, lambda жана функционалдык интерфейстер менен бул стереотиптердин баары жакында жок болот, акыры Java codeун жазуу чындап кыска көрүнөт.
package com.javacodegeeks.advanced.design;

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

8. КӨРҮНҮҮ

Биз буга чейин окуу куралынын 1-бөлүгүндө Javaдагы көрүнүү жана жеткorктүүлүк эрежелери жөнүндө бир аз сүйлөшкөнбүз. Бул бөлүктө биз бул теманы дагы бир жолу карап чыгабыз, бирок субкласстардын контекстинде. Класстарды жана интерфейстерди долбоорлоо (макаланын котормосу) - 2Ар кандай деңгээлдеги көрүнүш класстарга башка класстарды же интерфейстерди (мисалы, алар ар кандай пакеттерде же бири-биринин ичине уя салынган болсо) көрүүгө же субкласстарга ата-энелеринин ыкмаларын, конструкторлорун жана талааларын көрүүгө жана аларга кирүүгө мүмкүндүк берет же алдын алат. Кийинки бөлүмдө мурас, биз муну иш жүзүндө көрөбүз.

9. МУРАС

Мурас мамилелердин классын куруу үчүн негиз катары кызмат кылган an objectиге багытталган программалоонун негизги түшүнүктөрүнүн бири. Көрүнүү жана жеткorктүүлүк эрежелери менен бирге мурастоо класстарды кеңейтүүгө жана сактоого боло турган иерархияга түзүүгө мүмкүндүк берет. Концептуалдык деңгээлде Java'да мурастоо субклассинг жана кеңейтүү ачкыч сөзү менен бирге ата-эне класс менен ишке ашырылат. Субкласс ата-эне класстын бардык ачык жана корголгон элементтерин мурастайт. Кошумчалай кетсек, эгер экөө тең (подкласс жана класс) бир пакетте болсо, субкласс өзүнүн ата-эне классынын пакет-жеке элементтерин мурастайт. Айтылгандай, сиз эмнени иштеп чыгууга аракет кылып жатканыңызга карабастан, класс жалпыга ачык же анын субкласстарына көрсөткөн минималдуу ыкмалар топтомун кармануу абдан маанилүү. ParentМисалы, классты жана анын субклассын карап көрөлү 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";
    }
}
Мурас - бул абдан чоң тема, Java үчүн өзгөчө майда-чүйдөсүнө чейин көп. Бирок, бир нече эрежелерди карманууга оңой жана класс иерархиясынын кыскалыгын сактоого көп жардам бере турган эрежелер бар. Javaда ар бир субкласс акыркы деп жарыя кылынбаса, анын ата-энесинин тукум кууган ыкмаларын жокко чыгара алат. Бирок, ыкманы жокко чыгарылган деп белгилөө үчүн атайын синтаксис же ачкыч сөз жок, бул башаламандыкка алып келиши мүмкүн. Мына ошондуктан @Override annotationсы киргизилди : сиздин максатыңыз тукум кууп өткөн ыкманы жокко чыгаруу болгондо, аны кыскача көрсөтүү үчүн @Override annotationсын колдонуңуз . Java иштеп чыгуучулары долбоорлоодо дайыма туш болгон дагы бир дилемма - интерфейстерди ишке ашырууга каршы класс иерархияларын (конкреттүү же абстракттуу класстар менен) куруу. Мүмкүн болушунча класстарга же абстракттуу класстарга караганда интерфейстерге артыкчылык берүүнү сунуштайбыз. Интерфейстер жеңorрээк, текшерүү жана тейлөө оңой, ошондой эле ишке ашыруудагы өзгөрүүлөрдүн терс таасирин азайтат. Java стандарттык китепканасында прокси класстарды түзүү сыяктуу көптөгөн өнүккөн программалоо ыкмалары көбүнчө интерфейстерге таянат.

10. КӨП МУРАСЧЫЛЫК

C++ жана кээ бир башка тилдерден айырмаланып, Java бир нече тукум куучулукту колдобойт: Javaда ар бир класс бир гана түз ата-энеге ээ болушу мүмкүн (класс Objectиерархиянын жогору жагында жайгашкан). Бирок, класс бир нече интерфейсти ишке ашыра алат, ошондуктан интерфейсти стекелөө Java'да бир нече мураска жетишүүнүн (же симуляциялоонун) жалгыз жолу.
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
    }
}
Бир нече интерфейстерди ишке ашыруу чындыгында абдан күчтүү, бирок көп учурда ишке ашырууну кайра-кайра колдонуу зарылчылыгы Javaнын бир нече мурасты колдоонун жоктугун жеңүү жолу катары терең класс иерархиясына алып келет. 
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
    }
}
Жана башкалар... Java 8дин жакында чыккан versionсы демейки ыкманы киргизүү маселесин бир аз чечет. Демейки ыкмалардан улам интерфейстер иш жүзүндө келишимди гана эмес, ишке ашырууну да камсыз кылат. Демек, бул интерфейстерди ишке ашырган класстар да бул ишке ашырылган методдорду автоматтык түрдө мурастап алышат. Мисалы:
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
    }
}
бир нече мурас абдан күчтүү, бирок ошол эле учурда коркунучтуу курал экенин эстен чыгарбоо керек. Белгилүү "Өлүмдүн Алмазы" көйгөйү көбүнчө бир нече мурасты ишке ашыруудагы негизги кемчorк катары айтылып, иштеп чыгуучуларды класс иерархияларын абдан кылдаттык менен иштеп чыгууга мажбурлайт. Тилекке каршы, демейки ыкмалар менен Java 8 интерфейстери да бул кемчorктердин курмандыгы болуп калышат.
interface A {
    default void performAction() {
    }
}

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

interface C extends A {
    @Override
    default void performAction() {
    }
}
Мисалы, төмөнкү code үзүндүсү компиляцияланбай калат:
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
Бул учурда, Java тor катары an objectиге багытталган программалоонун бурчтук учурларынан качууга ар дайым аракет кылып келгенин айтуу туура болот, бирок тил өнүккөн сайын, алардын айрымдары күтүлбөгөн жерден пайда боло баштады. 

11. МУРАС АЛУУ ЖАНА КУРАМ

Бактыга жараша, мурас сиздин классты долбоорлоонун жалгыз жолу эмес. Көптөгөн иштеп чыгуучулар мураска караганда алда канча жакшы деп эсептеген дагы бир альтернатива - бул композиция. Идея абдан жөнөкөй: класстардын иерархиясын түзүүнүн ордуна, алар башка класстардан түзүлүшү керек. Бул мисалды карап көрөлү:
// E is not compilable unless it overrides performAction() as well
interface E extends B, C {
}
Класс Vehicleкыймылдаткычтан жана дөңгөлөктөн турат (жөнөкөйлүк үчүн четте калган көптөгөн башка бөлүктөр). VehicleБирок, класс да кыймылдаткыч  деп айтууга болот , ошондуктан аны мурастоо аркылуу долбоорлоого болот.
public class Vehicle extends Engine {
    private Wheels[] wheels;
    // ...
}
Кандай дизайн чечими туура болот? Жалпы негизги көрсөтмөлөр IS-A (бул) жана HAS-A (камтыган) принциптери катары белгилүү. IS-A - тукум куучулук мамиле: субкласс ошондой эле ата-эне класстын класс спецификациясын жана негизги класстын вариациясын канааттандырат. субкласс) өзүнүн ата-энесин кеңейтет. Эгер бир an object башкасын кеңейткенин билгиңиз келсе, дал келүү сынагын жасаңыз - IS -A (is).") Демек, HAS-A композициялык байланыш болуп саналат: класс an objectке ээ (же камтыган) көпчүлүк учурларда, HAS-A принциби бир нече себептерден улам IS-Aга караганда жакшыраак иштейт: 
  • Дизайн көбүрөөк ийкемдүү;
  • Модел туруктуураак, анткени өзгөрүү класс иерархиясы аркылуу жайылbyte;
  • Класс жана анын курамы ата-энени жана анын субклассын тыгыз байланыштырган композицияга салыштырмалуу эркин бириктирилген.
  • Класстагы ой жүгүртүүнүн логикалык поезди жөнөкөй, анткени анын бардык көз карандылыгы бир жерде камтылган. 
Кандай болбосун, мурас өзүнүн орду бар жана ар кандай жолдор менен бир катар учурдагы дизайн көйгөйлөрүн чечет, ошондуктан ага көңүл бурбай коюуга болбойт. Объектке багытталган моделиңизди иштеп чыгууда ушул эки альтернативаны эске алыңыз.

12. ИНКАПСУЛАЦИЯ.

Объектке багытталган программалоодо инкапсуляция концепциясы ишке ашыруунун бардык деталдарын (мисалы, иштөө режими, ички ыкмалар ж.б.) тышкы дүйнөдөн жашыруу болуп саналат. Инкапсуляциянын артыкчылыктары - туруктуулук жана өзгөртүү оңой. Класстын ички ишке ашырылышы жашырылган, класстын маалыматтары менен иштөө класстын жалпы ыкмалары аркылуу гана ишке ашат (эгерде сиз китепкананы же көптөгөн адамдар колдонгон алHowтарды иштеп чыгууда чыныгы көйгөй). Java'да инкапсуляция көрүү жана жеткorктүүлүк эрежелери аркылуу ишке ашат. Java-да талааларды эч качан түздөн-түз ачыкка чыгарбоо эң жакшы тажрыйба деп эсептелет, алуучулар жана орнотуучулар аркылуу гана (эгер талаалар акыркы деп белгиленбесе). Мисалы:
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;
    }
}
Бул мисал Java тorнде JavaBeans деп аталган нерсени эске салат : стандарттуу Java класстары конвенциялардын жыйындысына ылайык жазылган, алардын бири талааларга Getter жана Setter ыкмаларын колдонуу менен гана кирүүгө мүмкүндүк берет. Мурастоо бөлүмүндө баса белгилегендей, инкапсуляция принциптерин колдонуп, класстагы минималдуу жарыялоо келишимин дайыма карманыңыз. Жалпыга ачык болбошу керек болгон нерселердин баары купуя болушу керек (же сиз чечип жаткан маселеге жараша корголгон/пакет купуя). Бул узак мөөнөттүү келечекте үзгүлтүксүз өзгөртүүлөрдү киргизбестен (же жок дегенде аларды азайтпай) дизайнга эркиндик берүү менен төлөйт. 

13. КОРУТУНДУ КЛАССТАР ЖАНА МЕТОДДОР

Java тorнде класстын башка класстын субклассы болуп калышына жол бербөөнүн бир жолу бар: башка класс акыркы деп жарыяланышы керек. 
package com.javacodegeeks.advanced.design;

public final class FinalClass {
}
Метод декларациясындагы  ошол эле акыркы ачкыч сөз подкласстардын методду жокко чыгаруусуна жол бербейт.
package com.javacodegeeks.advanced.design;

public class FinalMethod {
    public final void performAction() {
    }
}
Класстын же методдордун акыркы болушу керекпи же жокпу, чечим кабыл алуунун жалпы эрежелери жок. Жыйынтыктоочу класстар жана методдор экстенсибилдүүлүктү чектейт жана класстын тукум кууп өтүшү керекпи же болбошу керекпи, же метод келечекте жокко чыгарылышы керекпи же жокпу, алдын ала ойлонуу өтө кыйын. Бул китепкана иштеп чыгуучулар үчүн өзгөчө маанилүү, анткени бул сыяктуу дизайн чечимдер китепкананын колдонуу мүмкүнчүлүгүн олуттуу чектеши мүмкүн. Java стандарттык китепканасында акыркы класстардын бир нече мисалдары бар, алардын эң белгилүүсү String классы. Алгачкы этапта, бул чечим иштеп чыгуучулардын сапты ишке ашыруу үчүн өз алдынча, "жакшы" чечимди табуу аракетин алдын алуу үчүн кабыл алынган. 

14. КИЙИНКИСИ ЭМНЕ

Сабактын бул бөлүгүндө биз Java тorнде an objectиге багытталган программалоо концепцияларын карадык. Биз ошондой эле контракттык программалоону тез карап чыктык, кээ бир функционалдык концепцияларга токтолдук жана тилдин убакыттын өтүшү менен кандайча эволюцияланганын көрдүк. Сабактын кийинки бөлүгүндө биз генериктерди жана алар программалоодо типтин коопсуздугуна болгон мамилебизди кандайча өзгөртөрүн таанышабыз. 

15. БУЛАК КОДУН ЖҮКТӨП АЛЫҢЫЗ

Булакты бул жерден жүктөп алсаңыз болот - advanced-java-part-3 Source: How to design Classes an
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION