从现有的超类字段中创建子类

时间:2011-06-24 21:07:51

标签: java superclass

我需要创建一个现有类的子类,我知道该怎么做,但是我需要能够在不修改超类的情况下基于现有的超类创建子类。

例如:

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;

}

6 个答案:

答案 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的来源,请复制它,添加访问其字段等所需的方法,然后将副本放在原始路径之前的类路径中。