Можно ли динамически внедрить родителя в иерархию классов в Java? - PullRequest
7 голосов
/ 01 февраля 2011

Учитывая иерархию классов:

A -> B -> C -> instanceOfC

возможно (и как) вставить класс временно во время выполнения, например, так:

A -> B -> B '-> C -> instanceOfC?

Ответы [ 4 ]

6 голосов
/ 01 февраля 2011

AspectJ

Это возможно, если вы используете AspectJ.AspectJ имеет оператор declare parents, который позволяет вам делать именно это, и через Weaving Time Weaving вы также сможете делать это во время выполнения.Однако вы не сможете сделать это на уже загруженных классах (по крайней мере, не легко, возможно, это сработает, если вы сначала выгрузите класс).

Ссылка:

Наследование против агрегации

НоМне кажется, вы пытаетесь решить не ту проблему здесь.Я бы сказал, попытайтесь заменить наследование агрегацией, пусть у C есть член типа D, которому делегируются функциональные возможности, и просто передайте другую реализацию D.Это называется шаблон стратегии , и это намного более чистый способ сделать что-то (и это тоже можно проверить)

3 голосов
/ 01 февраля 2011

API, который допускает наиболее инвазивные изменения в работающей JVM, это, вероятно, JVM Tool Interface . Он предназначен для разработки отладчиков, которые могут динамически изменять методы во время выполнения, чтобы упростить отладку и продолжить отладку.

Соответствующий вызов для замены определения класса был бы RedefineClass. Однако в документации сказано, что ее нельзя использовать для изменения иерархии класса:

Переопределение не должно добавлять, удалять или переименовывать поля или методы, изменять сигнатуры методов, изменять модификаторы или изменять наследование.

Поэтому я бы сказал, что вы не можете разумно изменять иерархию типов уже загруженных классов в неизмененной JVM. Либо измените иерархию классов во время загрузки (с помощью пользовательской ClassLoader и инструментария с байт-кодом, возможно, с использованием AOP), либо найдите другой подход.

1 голос
/ 01 февраля 2011

Нет, вы не можете.

Вы можете сделать:

A -> | interface for B and B` | -> C

или

     | B  | -> C
A -> 
     | B` | -> C`

Потеряв несколько хороших манер, вы могли бы сделать B + inner class = B'.

Например:

public class B<extraFunctionalityClassOrInterface> extends A {
    private extraFunctionalityClassOrInterface eF = null;
    // and B contents
}

Если экземпляр b.eF == null, то вы можете заключить b != B', но b == B.

0 голосов
/ 01 февраля 2011

Я не на 100%, но я думаю, что это было бы возможно, только если и B 'и C были загружены динамически.

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