我正在开发一个基于开源项目的应用程序。我们支付开发人员根据他们的代码制作我们自己的应用程序,封闭源代码。我们确实希望与原始软件包保持兼容,安全性和功能更新将与我们的应用程序合并。
当然,如果我大量修改原始代码,这里最大的问题是与新更新合并。我在网上搜索了最佳解决方案,其中我找到了像this one这样的网站。所以我决定不尽可能地修改原始代码。如果我想为现有功能添加功能,我会扩展原始类,使应用程序指向我的扩展类(这是一个足够小的修改,不是一个问题),并实现我的更改。
这里的问题是第三方类中的属性是我想要扩展的类型。在下面的例子中,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!";
}
}
一般来说,在应用程序,库等中......某些组件被设计为扩展(因为虽然是),而其他一些组件实际上并不是为了扩展而设计的。 但是修改现有组件通常不是扩展应用程序行为的方法。 因为现有的组件通常不是为了修改而设计的。他们的实际逻辑/处理可能会从版本强烈变化到另一个版本。这些可能会从源代码或其他任何内容中删除....因此,您将很难将原始源的更新合并到修改后的应用程序实现的源代码中。
长话短说:一个应用程序可能允许扩展但在这种情况下它还提供了扩展点,你不能以任何方式改变任何类。 如果要扩展原始源代码的某些部分,您必须知道实际应用程序是否设计为扩展,如果是,则如何。 如果它不是为扩展而设计的,那么您应该接受应用程序更新可能未集成(或难以集成)到已修改的应用程序中。
考虑使用适配器或装饰器模式,并使用组合而不是继承。例如:
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();
}
}