如何在Java中扩展最终类
这是我现在面临的问题。 我有一个类,让我们说Foo
,这个类定义了一个名为getBar
的方法,它返回一个Bar
实例。 类Bar
在Foo
定义,并且被声明为public static final
。 我想要做的是定义一个扩展Foo
的类MyFoo
,但我也希望通过添加我自己的function(方法,属性等)来扩展Bar
与MyBar
。 我也想让getBar
返回MyBar
。
问题是Bar
是最终的。 以下是我想要做的事情的说明:
public class Foo { Bar bar = new Bar(); public Bar getBar(){ return bar; } .... public static final class Bar { } }
我想做的是:
public class MyFoo extends Foo { public MyBar getBar(){ // here I want to return an instance of MyBar } public static final class MyBar extends Bar { // That's impossible since Bar is final } }
我怎样才能做到这一点?
[编辑]我正在为我的问题添加更多细节。 我实际上正在为Jenkins开发一个插件,在搜索之后,我意识到有一个插件可以提供我想要做的基本function, Foo
和Bar
。 我想定制Foo
和Bar
,因此它可以满足我的需求。 Foo是插件的主要类,并扩展了一个名为Builder的类。 Foo定义了一个名为perform
的方法,其中包含执行构建的所有操作。 Bar
包含用于配置目的的操作,Foo需要Bar来获取这些信息。
所以我想做的是使用MyFoo
扩展Foo并使用MyFoo
添加一些配置。 如你所见, MyFoo
需要通过调用getBar();
来获得这些配置getBar();
第二件事是我无法控制MyFoo
和MyBar
阻止我的是,我无法延伸Bar。 我怎样才能做到这一点?
基本上你不能。 看起来设计Bar
的开发人员不会扩展它 – 所以你不能扩展它。 你需要寻找一个不同的设计 – 可能是一个不使用inheritance的设计……当然,假设你不能改变现有的代码。
(如果不了解更多关于这里的真正目标 – 整个系统的设计,很难给出更具体的建议。)
您不能扩展声明为final
的类。 但是,您可以创建一个名为Wrapper
的中间类。 此Wrapper将基本上包含原始类的实例,并提供替代方法来根据您要执行的操作来修改对象的状态。
当然,这不会提供对final
类的私有和受保护字段的访问,但是您可以使用其getter和setter方法,结合您在Wrapper
类中声明的新方法和字段来获得您想要的结果,或者比较接近的东西。
另一种解决方案是,如果没有合理的理由,则不要声明final
的类。
你无法扩展final
类 – 这是final
关键字的目的。
但是,(至少)有两种解决方法:
- 该类位于Jenkins项目中,该项目是开源的,因此您只需下载项目,对类进行所需的更改并重新构建jar
- 有点像黑客,但你可以使用像Javassist这样的库来替换内存中类的实现
你不能扩展最终的类,这是宣告类最终的要点。 您可以定义最终类inheritance的接口和将调用委托给包装的最终类的包装类。 问题是为什么要把class级列为最终。
可能你想要的是一个代理。 它很容易实现。 这是一篇很棒的文章: http : //java.dzone.com/articles/power-proxies-java
例如,我们不能在TreeSet集合中添加StringBuffer,因为TreeSet不是Interface Comparable的子代:
public class Main(){ public static void main(String[] args){ TreeSet treeSetSB = new TreeSet(); treeSetSB.add(new StringBuffer("A")); //error, Comparable is not implemented }
但我们可以使用包装器来实现Comparable:
class myWrap implements Comparable{ TreeSet treeset; public myWrap() { this.treeset=new TreeSet<>(); } public TreeSet getTreeset() { return treeset; } public void setTreeset(TreeSet treeset) { this.treeset = treeset; } } public class Main(){ public static void main(String[] args){ myWrap myWrap =new myWrap(); TreeSet myTrs =myWrap.getTreeset(); myTrs.add("b"); // no error anymore myTrs.add("a"); myTrs.add("A"); System.out.println(myTrs); }
如果它实现了一些接口, Decorator Design模式可以解决问题。