Сделать подкласс из существующего поля суперкласса - PullRequest
1 голос
/ 25 июня 2011

Мне нужно создать подкласс существующего класса, что я знаю, как сделать, но мне нужно иметь возможность создавать подкласс на основе существующего суперкласса без изменения суперкласса.

Например:

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.

EDIT

Важное ограничение, я не думал, что все скажут мне отредактировать Foo. Я не могу изменить Foo, этот класс находится в библиотеке, которую я не могу редактировать, поэтому то, что я хочу сделать, должно быть сделано без редактирования Foo.

EDIT2

Вот собственно Foo, это класс ChunkProvider из Minecraft.

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 ]

3 голосов
/ 25 июня 2011

Существует способ обойти это, и он не наследует 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...
}
2 голосов
/ 25 июня 2011

Если у закрытой переменной Foo _a нет метода доступа, и вы не можете изменить Foo, то нет никакого способа, кроме некоторого отражения , сделать то, что вы описываете. Вы просто не имеете доступа к Foo._a.

1 голос
/ 25 июня 2011

Итерируйте по 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);
}

валяется именно для таких случаев.

0 голосов
/ 25 июня 2011

Если у вас есть источник для Foo, скопируйте его, добавив методы, необходимые для доступа к его полям и т. Д., А затем поместите вашу копию в путь к классам перед оригиналом.

0 голосов
/ 25 июня 2011

Добавьте конструктор 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;
}
0 голосов
/ 25 июня 2011

просто позвоните

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

, где находятся ваши вопросительные знаки.

вы не можете сделать новый экземпляр Bar foo.(Если ты можешь, я определенно узнал кое-что сегодня).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...