Java, как расширить стороннее приложение при сохранении совместимости - PullRequest
0 голосов
/ 10 сентября 2018

Я занимаюсь разработкой приложения на основе проекта с открытым исходным кодом. Мы заплатили разработчикам за создание собственного приложения с закрытым исходным кодом на основе их кода. Мы хотим оставаться совместимыми с оригинальным пакетом, обновления безопасности и функций будут объединены с нашим приложением.

Конечно, самая большая проблема здесь - это слияние с новыми обновлениями, если я сильно изменил исходный код. Я искал в Интернете лучшее решение, и среди других я нашел такие сайты, как этот . Поэтому я решил не изменять исходный код настолько, насколько мог. Если я хочу добавить функциональность к существующей функции, я расширяю исходный класс, заставляю приложение указывать на мой расширенный класс (который является достаточно маленькой модификацией, чтобы не создавать проблем) и внедряю мои изменения.

Проблема здесь в том, что свойства в стороннем классе относятся к типу, который я также хочу расширить. В приведенном ниже примере class A вносит некоторые изменения в свойство myClass, которые я хочу продолжать. Но class B, который расширяет class A, содержит свойство с типом, который расширяет MyClass, здесь MyCustomClass. Внутри class B Я хочу, чтобы свойство myCustomClass было расширением myClass, любые изменения, сделанные в myClass, должны быть доступны в myCustomClass.

Насколько я знаю, приведение myClass к myCustomClass невозможно, так как myClass просто не относится к типу myCustomClass. Так какое же лучшее решение здесь, которое поддерживает совместимость с class A и не требует простого копирования всего кода из class A, поскольку это создаст точно такие же проблемы, если class A получит обновление?

Вот пример кода, который должен объяснить мой вопрос лучше:

// Classes 'A' and 'MyClass' are 3rd party, I do not want to edit them
public class A {
    private MyClass myClass;

    A(){
        myClass = new MyClass();

        // Changes I want to keep doing
        doSomething();
    }

    public void doSomething(){
        // Do some calculations to myClass and modify it accordingly 
    }

    public MyClass getMyClass(){
        return myClass
    }
}


// Classes 'B' and 'MyCustomClass' are 1st party, I can do anything I want with them :)
public class B extends A{
    private MyCustomClass myCustomClass;        

    B(){
        super();

        myCustomClass = ?????????;


        // Extremely important message, this should keep working
        System.out.println(myCustomClass.verySpecialString);

        // Build further on made modifications, this should keep working too
        useModificationsByClassA();
    }

    public void useModificationsByClassA(){
        // Use result of class A's calculations in order to continue
    }
}


public class MyCustomClass extends MyClass{
    private String verySpecialString;

    MyCustomClass(){
        super();

        verySpecialString = "Hey!";
    }
}

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Рассмотрите возможность использования шаблона адаптера или декоратора и используйте композицию вместо наследования.Например:

public class B {
    private final A a;        
    private final MyCustomClass myCustomClass;

    B(A a) {
        this.a = a;
        myCustomerClass = new MyCustomClass(a.getMyClass());
    }

   public void doSomething()  {
     a.doSomething();   // updates the state of a.myClass.
     myCustomerClass.doSomething();  // use the change of a.myClass to do more stuff         
   }
}

public class MyCustomClass {
   private final MyClass myClass;
   private String verySpecialString;

   public MyCustomClass(MyClass myClass) {
      this.myClass = myClass;
   }

   public void doSomething() {
      verySpecialString = "Hey!" + myClass.getSomeResult();
   }
}
0 голосов
/ 10 сентября 2018

В общем случае в приложении, библиотеке и т. Д. Некоторые компоненты предназначены для расширения (хотя и для), а некоторые другие компоненты действительно не предназначены для расширения.
Но изменение существующего компонента, как правило, не является способом расширения поведения приложения.
Потому что существующие компоненты, как правило, не предназначены для изменения. Их фактическая логика / обработка может сильно измениться от версии к другой. Они могут быть удалены из исходного кода или чего-либо еще .... Таким образом, вам будет сложно объединить обновления исходного кода с исходным кодом модифицированной реализации приложения.

Короче говоря: приложение может разрешать расширение, но в этом случае оно также предоставляет точки расширения, вы не можете изменить какой-либо класс.
Если вы хотите расширить некоторые части исходного исходного кода , вы должны знать, предназначено ли фактическое приложение для расширения, и если да, то как .
Если он не предназначен для расширения, , вы должны согласиться с тем, что обновления приложения могут быть не интегрированы (или их трудно интегрировать) в измененное приложение.

...