Java如何在保持兼容性的同时扩展第三方应用程序

Java如何在保持兼容性的同时扩展第三方应用程序,java,open-source,extend,Java,Open Source,Extend,我正在开发一个基于开源项目的应用程序。我们付钱给开发人员,让他们根据自己的代码开发自己的封闭源代码应用程序。我们确实希望与原始软件包保持兼容,安全和功能更新将与我们的应用程序合并 当然,这里最大的问题是,如果我大量修改了原始代码,就会合并新的更新。我在网上搜索最佳解决方案,在其他网站中,我找到了类似的网站。所以我决定不尽可能多地修改原始代码。如果我想向现有特性添加功能,我将扩展原始类,使应用程序指向我的扩展类(这是一个足够小的修改,不会成为问题),并实现我的更改 这里的问题是第三方类中的属性属于

我正在开发一个基于开源项目的应用程序。我们付钱给开发人员,让他们根据自己的代码开发自己的封闭源代码应用程序。我们确实希望与原始软件包保持兼容,安全和功能更新将与我们的应用程序合并

当然,这里最大的问题是,如果我大量修改了原始代码,就会合并新的更新。我在网上搜索最佳解决方案,在其他网站中,我找到了类似的网站。所以我决定不尽可能多地修改原始代码。如果我想向现有特性添加功能,我将扩展原始类,使应用程序指向我的扩展类(这是一个足够小的修改,不会成为问题),并实现我的更改

这里的问题是第三方类中的属性属于我也想扩展的类型。在下面的示例中,
class A
对属性
myClass
进行了一些修改,我希望它继续这样做。但是扩展了
class A
class B
包含一个类型扩展了
MyClass
本身的属性,这里是
MyCustomClass
。在
class B
中,我希望属性
myCustomClass
myClass
的扩展,对
myClass
所做的任何更改都可以在
myCustomClass
中访问

据我所知,将
myClass
转换为
myCustomClass
是不可能的,因为
myClass
根本不是
myCustomClass
类型。 那么,什么是保持与
A类
兼容的最佳解决方案,而不只是从
A类
复制所有代码,因为如果
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!";
    }
}

一般来说,在应用程序、库等中。。。有些组件被设计为可扩展的(因为尽管如此),而有些组件实际上并不是被设计为可扩展的。
但修改现有组件通常不是扩展应用程序行为的方式。
因为现有组件通常不会被修改。从一个版本到另一个版本,它们的实际逻辑/处理可能会发生很大的变化。这些可以从源代码或其他任何内容中删除。。。。 因此,您将很难将原始源代码的更新合并到应用程序的修改实现的源代码中

长话短说:应用程序可能允许扩展,但在这种情况下,它还提供扩展点,您不能以任何方式更改任何类。
如果您想扩展原始源代码的某些部分,您必须知道实际应用程序是否设计为扩展,如果是,如何扩展

如果它不是为扩展而设计的,您应该接受应用程序更新可能没有集成(或很难集成)到修改后的应用程序中。考虑使用适配器或装饰器模式,并使用组合而不是继承。例如:

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();
   }
}

我认为你的愿望不可能实现。一旦您扩展了代码库,您就有责任维护这些更改。保持两者同步的唯一方法是将更改作为开源提交到原始项目。这样,将来的版本也会有您的更改。这意味着原始代码提供者必须同意将您的内容合并到中。@duffymo,我的项目与原始代码相差很大。那不行。如果这是不可能的,那么最接近的解决方案是什么?或者我唯一能做的就是复制A类的代码?复制代码?天哪,不是。你可以把这个库作为一个依赖项来使用,并编写你自己的扩展。您承认并接受这样的风险,即如果库进行了更改,您将不得不升级以保持同步,或者保留旧版本。你应该视图书馆为不可侵犯的——不要以任何方式修改它。扩展,包装,使用合成,但不要通过编辑他们的源文件来扩展。是的,我知道我必须做一些工作来保持更新。那很好。我在这里试图解决的一个具体问题是更改一些按钮的布局,最好不要编辑原始代码。在一个扩展中,我该怎么做?Swing UI?哦,孩子。现在您遇到了一个问题,因为我怀疑作者是否对扩展点考虑过多,并使您能够轻松地完成这样的事情。您可以编写自己的JPanel,为它提供您想要的按钮,并使用侦听器对它们进行配置,这些侦听器可以调用您希望它们拥有的库。但这些代码都是你的。您只能使用它们的API向按钮侦听器添加调用以执行所需的任务。好的,但是如果它只是不被扩展,有没有可靠的方法来添加更改?还是我只是运气不好?解决此类问题的常用方法是什么?可靠吗?您可能永远不需要更改许多类/文件。您甚至可能需要更改测试类(如果有)。其实没有太多的解决方案:在第一次将应用程序作为内部应用程序进行分叉可能很好,但以后可能会有风险。谢谢。我以前考虑过这个解决方案并尝试过,但并不喜欢它,因为它破坏了很多东西。但我想我没有太多的选择,我会再投资一些来让这一切顺利进行。如果这是我最终要做的事情,将选择答案:)@Andrew S OP需要更改现有类以使更改生效。因此,事实上,在没有真正保护您的情况下,组合将很难实现,因为如果您用另一个类(即compositor类)修改现有类,则必须更改对已更改的现有类的所有引用,并监视是否有修改。