#java #reflection
#java #отражение
Вопрос:
Я создаю библиотеку, и в этой библиотеке она будет содержать фигуры, точнее, правильные и неправильные многоугольники, эта библиотека должна позволять пользователям не только использовать мои фигуры, но и во время выполнения иметь возможность создавать свои собственные.
На данный момент у меня есть несколько фигур, представленных следующим образом:
Polygon
|- PolygonRegular
|- Square
|- Circle
|- EquilateralTriangle implements Triangle
|- PolygonIrregular
|- Trapeze
|- IsoscelesTriangle implements Triangle
Теперь в этом заданном сценарии, допустим, я как пользователь хочу создать свой пользовательский полигон, в данном случае «ScaleneTriangle», в котором в дальнейшем также будет реализован интерфейс Triangle, моя библиотека должна легко предоставлять инструменты, необходимые для создания этой «фабрики» для создания фигур.
//Though I don't know the code, what I wanted to achieve, would be something very close to:
Point2D[] points = new Point2D[]{
new Point2D.Float(0f, 0f),
new Point2D.Float(0.25f, 0f),
new Point2D.Float(1f, 1f),
};
ContentFactory.create(PolygonIrregular.class, "ScaleneTriangle", points);
Однако я понятия не имею, как я могу создать ContentFactory точно так же, чтобы создавать классы во время выполнения так же, как это было волшебно… Мне также волшебным образом придется создавать экземпляры этих классов.
Чтобы дать больше понимания на случай, если проблема не была прояснена: представьте, что я пользователь, всплывающее окно canvas, нарисуйте новую фигуру. Подтверждает. С этой новой формой создается представление buttonpresentation. Каждый раз, когда пользователь нажимает на buttonRepresentation, создается элемент с формой.
Комментарии:
1. Вы рассматривали возможность использования javassist ?
2. Если возможно, я бы предпочел сделать это с помощью простой java.
3. Можно создать свой собственный java-код и скомпилировать его во время выполнения, используя реализации JavaCompiler. Тогда вам пришлось бы загружать байт-код скомпилированного класса во время выполнения и использовать методы через отражение.
4.Рассматривали ли вы возможность проконсультироваться с Javadoc?
Class.newInstance()
например? Никаких внешних библиотек не требуется.5. Почему вы моделируете разные типы полигонов как классы? Похоже, они не ведут себя полиморфно. Получение точек многоугольника является мономорфным. И каждое свойство также может быть сохранено в списке свойств полигона (как поле универсального класса). Я не могу представить полиморфный метод, который имеют все классы polygon (и который удовлетворяет принципу подстановки Лискова).
Ответ №1:
Есть несколько способов сделать это.
В этой статье это делается с помощью jOOQ, но вы можете повторно реализовать их метод, если не хотите дополнительной зависимости. (архив для потомков)
Способ, которым я делал это в прошлом (просто в качестве теста), заключался в использовании компилятора из janino для компиляции строки в класс, который реализует интерфейс, который известен во время компиляции. Это в kotlin, но было бы легко преобразовать в Java.
package com.dmercer
import org.codehaus.janino.SimpleCompiler;
import org.codehaus.janino.util.Benchmark
fun main(args: Array<String>) {
val sourceString = """
package com.dmercer;
public class B implements BasicInterface {
@Override
public void runMethod() {
System.out.println("Hello from compiled method");
}
}
""".trimIndent()
val compiler = SimpleCompiler()
compiler.cook(sourceString)
val classLoader = compiler.classLoader
val compiledClass = classLoader.loadClass("com.dmercer.B")// as IDBMethod
val classInstance = compiledClass.newInstance() as BasicInterface
classInstance.runMethod()
}
Комментарии:
1. Я смог выполнить это с помощью JavaCompiler. Я все равно отмечу это как правильное, поскольку большинство вещей, которые я делал с компилятором, отображаются в вашем коде.
2. Отлично. Было бы хорошо, если бы вы могли опубликовать существенную часть своего решения, если сможете, для любого будущего пользователя, который столкнется с этим.