1

我需要创建现有类的子类,我知道该怎么做,但我需要能够基于现有超类创建子类,而无需修改超类。

例如:

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 的情况下完成。

编辑2

这是实际的 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;

}
4

6 回答 6

3

有一种解决方法,不是继承Foo,而是组合它并委托给它的方法。

我注意到“真实”Foo实现了一个接口。如果您可以围绕该接口而不是具体设计代码FooBar则可以是这样的:

public class Bar implements IFoo {
  public Bar(IFoo foo, ...) {
    _foo = foo;
  }
  private IFoo _foo;
  // implement IFoo delegating all calls to _foo...
}
于 2011-06-24T21:38:42.603 回答
2

如果 Foo 的私有变量 _a 没有访问器方法并且您无法更改 Foo ,那么除了一些反射之外,就没有办法按照您的描述进行操作。您根本无法访问 Foo._a。

于 2011-06-24T21:24:18.340 回答
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);
}

只是为了这样的不测事件。

于 2011-06-24T21:26:36.590 回答
0

打电话

super(foo.getA()) // assuming you have a getA method

你的问号在哪里。

您不能将新的 Bar 实例设为 foo。(如果可以的话,我今天肯定会学到一些东西)。

于 2011-06-24T21:09:59.303 回答
0

添加一个Foo以 aFoo作为参数并复制 的_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;
}
于 2011-06-24T21:10:12.673 回答
0

如果您有 Foo 的源代码,请将其复制并添加访问其字段等所需的方法,然后将您的副本放在原始类路径之前的类路径中。

于 2011-06-24T21:33:50.683 回答