我需要创建一个现有类的子类,我知道该怎么做,但是我需要能够在不修改超类的情况下基于现有的超类创建子类。
例如:
public class Foo
{
public Foo(int a)
{
_a = a;
}
private int _a;
}
public class Bar extends Foo
{
public Bar(int a, int b)
{
super(a);
_b = b;
}
public Bar(Foo foo, int b)
{
???? //<----What do I do here?
_b = b;
}
private int _b;
}
public static class Baz
{
static void Main(String[] args)
{
Foo foo = new Foo(1);
Bar bar = new Bar(foo, 2); //<---- How do I set this up?
}
}
因此在上面的示例中,它将使用现有的Foo实例并将其转换为Bar并将_b字段设置为2.
修改
重要的限制,我不认为每个人都会告诉我编辑Foo。我不能改变Foo,那个类在我无法编辑的库中,所以我想要做的就是在不编辑Foo的情况下完成。
EDIT2
这是实际的Foo,它是Minecraft的ChunkProvider类。
public class ChunkProvider
implements IChunkProvider
{
public ChunkProvider(World world, IChunkLoader ichunkloader, IChunkProvider ichunkprovider)
{
chunkSet = new HashSet();
chunkMap = new HashMap();
chunkList = new ArrayList();
field_28064_b = new EmptyChunk(world, new byte[32768], 0, 0);
field_28066_g = world;
field_28069_d = ichunkloader;
field_28070_c = ichunkprovider;
}
//(Snip) There are no GetXXX members for the below fields.
private Set chunkSet;
private Chunk field_28064_b;
private IChunkProvider field_28070_c;
private IChunkLoader field_28069_d;
private Map chunkMap;
private List chunkList;
private World field_28066_g;
}
答案 0 :(得分:3)
有一种解决方法,它不是继承Foo
,而是组成它并委托给它的方法。
我注意到“真正的”Foo
实现了一个接口。如果您可以围绕该界面设计代码而不是围绕具体Foo
设计代码,Bar
可以是这样的:
public class Bar implements IFoo {
public Bar(IFoo foo, ...) {
_foo = foo;
}
private IFoo _foo;
// implement IFoo delegating all calls to _foo...
}
答案 1 :(得分:2)
如果Foo的私有变量_a没有访问器方法而你无法改变Foo,那么就没有办法(缺少某些reflection)去做你所描述的。你很简单,无法访问Foo._a。
答案 2 :(得分:1)
遍历Foo.class.getDeclaredFields()
,寻找名为_a
的广告。在字段上调用Field.setAccessible(true)
,然后Field.getValue()
将为您提供所需的值。
我保留了这个更通用的代码
@SuppressWarnings("unchecked")
public static <T> T getFieldValue(Object target, String name) throws NoSuchFieldException, IllegalAccessException {
Class<? extends Object> c = target.getClass();
Field field = findField(c, name);
if (field == null)
throw new NoSuchFieldException(name);
field.setAccessible(true);
return (T) field.get(target);
}
public static Field findField(Class<? extends Object> clas, String name) {
if (clas == null)
return null;
Field[] declaredFields = clas.getDeclaredFields();
for (Field field : declaredFields) {
if (field.getName().equals(name))
return field;
}
return findField(clas.getSuperclass(), name);
}
只是因为这种可能性而四处闲逛。
答案 3 :(得分:0)
只需致电
super(foo.getA()) // assuming you have a getA method
您的问号在哪里。
你无法使新的Bar实例成为foo。 (如果可以,我今天肯定会学到一些东西)。
答案 4 :(得分:0)
添加一个Foo
构造函数,该构造函数将Foo
作为参数并复制_a
,然后调用您指定的构造函数。
编辑:
public class Bar extends Foo
{
public Bar(int a, int b)
{
super(a);
_b = b;
}
public Bar(Foo foo, int b)
{
super(foo.getA(),b); <------
_b = b;
}
private int _b;
}
答案 5 :(得分:0)
如果您拥有Foo的来源,请复制它,添加访问其字段等所需的方法,然后将副本放在原始路径之前的类路径中。