JavaRush /Блоги Java /Random-TG /Мероси сершумор дар Java. Муқоисаи таркиб ва мерос
HonyaSaar
Сатҳи
Москва

Мероси сершумор дар Java. Муқоисаи таркиб ва мерос

Дар гурӯҳ нашр шудааст
Чанде пеш ман дар бораи мерос, интерфейсҳо ва таркиб дар Java якчанд паём навишта будам. Дар ин мақола, мо мероси сершуморро дида мебароем ва сипас дар бораи манфиатҳои таркиб бар мерос омӯхта метавонем.
Мероси сершумор дар Java.  Муқоисаи таркиб ва мерос - 1

Мероси чандкарата дар Java

Мероси сершумор қобorяти сохтани синфҳо бо якчанд синфҳои волидайн мебошад. Баръакси дигар забонҳои маъмули ба an object нигаронидашуда, ба монанди C++, Java мероси синфҳои сершуморро дастгирӣ намекунад. Вай аз сабаби эҳтимоли дучор шудан бо "мушкилоти алмос" онро дастгирӣ намекунад ва ба ҷои он, пешниҳоди як навъ равиши ҳамаҷониба барои ҳалли он бо истифода аз имконоти беҳтарине, ки мо метавонем натиҷаи мероси шабеҳро ба даст орем, афзалтар медонад.

"Мушкилоти алмос"

Барои соддатар фаҳмидани мушкилоти алмос, биёед фарз кунем, ки мероси сершумор дар Java дастгирӣ карда мешавад. Дар ин ҳолат, мо метавонем синфҳоро бо иерархияи дар расми зер нишон додашуда ба даст орем. иерархияи синфи алмосФарз мекунем, ки SuperClassин як синфи абстрактист, ки усули муайянро тавсиф мекунад ва синфҳо ClassAва ClassBсинфҳои воқеӣ мебошанд. SuperClass.java
package com.journaldev.inheritance;
public abstract class SuperClass {
   	public abstract void doSomething();
}
ClassA.java
package com.journaldev.inheritance;
public class ClassA extends SuperClass{
    @Override
 public void doSomething(){
        System.out.println("Какая-то реализация класса A");
    }
  //собственный метод класса  ClassA
    public void methodA(){
    }
}
Акнун, фарз кунем, ки синф ClassCаз ClassAва ClassBҳамзамон мерос мегирад ва ҳамзамон татбиқи зеринро дорад:
package com.journaldev.inheritance;
public class ClassC extends ClassA, ClassB{
    public void test(){
        //вызов метода родительского класса
        doSomething();
    }
}
Аҳамият диҳед, ки усул test()усули doSomething()синфи волидайнро даъват мекунад, ки ин боиси номуайянӣ мегардад, зеро компилятор намедонад, ки кадом усули суперклассро даъват кардан лозим аст. Аз сабаби шакли диаграммаи мероси синфӣ дар ин вазъият, ки ба контури алмоси паҳлӯӣ шабоҳат дорад, масъала «Мушкилоти алмос» номида мешавад. Ин сабаби асосии он аст, ки Java мероси якчанд синфро дастгирӣ намекунад. Дар хотир доред, ки ин мушкилот бо мероси синфҳои сершумор метавонад бо се синфе, ки ҳадди аққал як усули умумӣ доранд, рух диҳад.

Мерос ва интерфейсҳои сершумор

Шумо шояд пай бурдед, ки ман ҳамеша мегӯям, ки "мероси сершумор дар байни синфҳо дастгирӣ намешавад", аммо он дар байни интерфейсҳо дастгирӣ карда мешавад. Намунаи оддӣ дар зер нишон дода шудааст: InterfaceA.java
package com.journaldev.inheritance;
public interface InterfaceA {

    public void doSomething();
}
InterfaceB.java
package com.journaldev.inheritance;

public interface InterfaceB {

    public void doSomething();
}
Аҳамият диҳед, ки ҳарду интерфейс усулҳои якхела доранд. Акнун биёед бигӯем, ки мо интерфейсе дорем, ки аз ҳарду интерфейс мерос мегирад. InterfaceC.java
package com.journaldev.inheritance;

public interface InterfaceC extends InterfaceA, InterfaceB {

    //метод, с тем же названием описан в  InterfaceA и InterfaceB
    public void doSomething();
Здесь, все идеально, поскольку интерфейсы – это только резервирование/описание метода, а реализация самого метода будет в конкретном классе, реализующем эти интерфейсы, таким образом нет ниHowой возможности столкнуться с неопределенностью при множественном наследовании интерфейсов. Вот почему, классы в Java могут наследоваться от нескольких интерфейсов. Покажем на примере ниже. InterfacesImpl.java
package com.journaldev.inheritance;

public class InterfacesImpl implements InterfaceA, InterfaceB, InterfaceC {

    @Override
    public void doSomething() {
        System.out.println("doSomething реализация реального класса ");
    }

    public static void main(String[] args) {
        InterfaceA objA = new InterfacesImpl();
        InterfaceB objB = new InterfacesImpl();
        InterfaceC objC = new InterfacesImpl();

        //все вызываемые ниже методы получат одинаковую реализацию конкретного класса

        objA.doSomething();
        objB.doSomething();
        objC.doSomething();
    }
}
Возможно, вы обратor внимание, что я каждый раз, когда я переопределяю метод описанный в суперклассе or в интерфейсе я использую аннотацию @Override. Это одна из трех встроенных Java-аннотаций и вам следует всегда использовать ее при переопределении методов.

Композиция How спасение

Так что же делать, если мы хотим использовать функцию methodA() класса ClassA и methodB() класса ClassB в ClassС? Решением этого может стать композиция – переписанная version ClassC реализующая оба метода классов ClassA и ClassB, также имеющая реализацию doSomething() для одного из an objectов. ClassC.java
package com.journaldev.inheritance;

public class ClassC{

    ClassA objA = new ClassA();
    ClassB objB = new ClassB();

    public void test(){
        objA.doSomething();
    }

    public void methodA(){
        objA.methodA();
    }

    public void methodB(){
        objB.methodB();
    }
}

Композиция or наследование?

Хорошим тоном программирования на Java является – использовать преимущества композиции перед наследованием. Мы рассмотрим некоторые аспекты в пользу такого подхода.
  1. Предположим, мы имеем следующую связку классов родитель-наследник:

    ClassC.java

    package com.journaldev.inheritance;
    
    public class ClassC{
    
    public void methodC(){
      	}
    
    }

    ClassD.java

    package com.journaldev.inheritance;
    
    public class ClassD extends ClassC{
    
        public int test(){
            return 0;
        }
    }

    Код выше прекрасно компorруется и работает, но что, если ClassC будет реализован иначе:

    package com.journaldev.inheritance;
    
    public class ClassC{
    
        public void methodC(){
        }
    
        public void test(){
        }
    }

    Отметьте, что метод test() уже существует в классе наследнике, но возвращает результат другого типа. Теперь ClassD, в случае если вы используете IDE, не будет скомпorрован. Вам будет рекомендовано изменить тип возвращаемого результата в классе наследнике or в суперклассе.

    Теперь представим себе такую ситуацию, где имеется многоуровневое наследование классов и суперкласс не доступен для наших изменений. Теперь, чтобы избавиться от ошибки компиляции, у нас нет других вариантов, кроме How изменить сигнатуру or Name метода подкласса. Также нам придется внести изменения во все места, где этот метод вызывался. Таким образом, наследование делает наш code хрупким.

    Проблема, описанная выше, никогда не встречается в случае композиции, и поэтому делает последнюю более предпочтительной перед наследованием.

  2. Следующая проблема с наследованием заключается в том, что мы демонстрируем все методы родителя клиенту. И если суперкласс разработан не очень корректно и содержит дыры в «безопасности». Тогда, несмотря на то, что мы fully позаботимся о безопасности при реализации нашего подкласса, мы все равно будем зависеть от ущербной реализации класса-родителя.

    Композиция помогает нам в обеспечении контролируемого доступа к методам суперкласса, тогда How наследование не поддерживает ниHowого контроля над его методами. Это - также одно из главных преимуществ композиции над наследованием.

  3. Бартарии дигари таркиб дар он аст, ки он ҳангоми даъват кардани усулҳо чандирӣ медиҳад. Татбиқи синфи ClassCдар боло тавсифшуда оптималӣ нест ва ҳатмии барвақтро ба усули даъватшуда истифода мебарад. Тағироти ҳадди ақал ба мо имкон медиҳад, ки усули зангро чандир созем ва ба дер ҳатмӣ (ҳатмӣ дар вақти корӣ) иҷозат диҳем.

    ClassC.java

    package com.journaldev.inheritance;
    public class ClassC{
        SuperClass obj = null;
        public ClassC(SuperClass o){
            this.obj = o;
        }
        public void test(){
            obj.doSomething();
        }
    
        public static void main(String args[]){
            ClassC obj1 = new ClassC(new ClassA());
            ClassC obj2 = new ClassC(new ClassB());
    
            obj1.test();
            obj2.test();
        }
    }

    Барномаи боло нишон медиҳад:

    doSomething implementation of A
    doSomething implementation of B

    Ин чандирии даъвати методӣ бо мерос дида намешавад, ки таркибро беҳтарин равиш месозад.

  4. Санҷиши воҳидҳо дар мавриди таркиб осонтар аст, зеро мо медонем, ки барои ҳама усулҳои дар суперкласс истифодашуда мо метавонем санҷишҳоро нопадид кунем, дар ҳоле ки дар мерос мо аз суперкласс вобастаем ва намедонем, ки усулҳои синфи волидайн чӣ гунаанд истифода мешавад. Ҳамин тавр, аз сабаби мерос мо бояд тамоми усулҳои суперклассро санҷем, ки ин кори нодаркор аст.

    Идеалӣ, мерос бояд танҳо вақте истифода шавад, ки муносибати " аст-a " барои синфҳои волидайн ва кӯдакон дуруст бошад, вагарна таркиб бояд бартарӣ дода шавад.

Мақолаи аслӣ
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION