#scala
Вопрос:
Здравствуйте, я хотел бы создать универсальную оболочку в scala, чтобы отслеживать изменения значения любого типа. Я не знаю/до сих пор не нашел других способов, и я думал о создании класса, и я пытался использовать динамику, но у нее есть некоторые ограничения.
case class Wrapper[T](value: T) extends Dynamic {
private val valueClass = value.getClass
def applyDynamic(id: String)(parameters: Any*) = {
val objectParameters = parameters map (x => x.asInstanceOf[Object])
val parameterClasses = objectParameters map (_.getClass)
val method = valueClass.getMethod(id, parameterClasses:_*)
val res = method.invoke(value, objectParameters:_*)
// TODO: Logic that will eventually create some kind of event about the method invoked.
new Wrapper(res)
}
}
С этим кодом у меня возникают проблемы при вызове метода plus(» «) для двух целых чисел, и я не понимаю, почему. Разве в классе Int нет метода» «? Ошибка, которую я получаю, когда пытаюсь добавить как с типом оболочки/Int, так и с типом:
var wrapped1 = Wrapper(1)
wrapped1 = wrapped1 Wrapper[2] // or just 2
type mismatch;
found : Wrapper[Int]/Int
required: String
Почему он ожидает строку?
Если возможно, было бы также неплохо иметь возможность беспрепятственно работать как с оболочкой[T], так и с методами T, например
val a = Wrapper[Int](1)
val b = Wrapper[Int](2)
val c = 3
a b // Wrapper[Int]. (Wrapper[Int])
a c // Wrapper[Int]. (Int)
c a // Int. (Wrapper[Int])
Комментарии:
1. В конце концов вы столкнетесь с тем фактом, что примитивы распаковываются в Scala. Я написал 20-страничную статью о том, что именно вы пытаетесь сделать, и это только верхушка айсберга. В зависимости от того, как далеко вы хотите зайти, вы столкнетесь с миллионом различных проблем. Tl;dr это действительно невозможно в полном объеме без написания плагина компилятора, чтобы явно изменить то, как работают определенные вещи.
Ответ №1:
Также, если вы хотите сделать прокси-сервер, который будет получать никаких изменений нужные значения, вы, вероятно, не без агентов(https://dzone.com/articles/java-agent-1), потому что это заставит вас сделать код модификации байт-кода, который принимает окончательное классы и примитивы, чтобы принять ваш прокси вместо этого, и это потребует более перехватив изменения «просто класс», но и все классы членов жюри и произвести происхождения-стоимостного анализа и так далее. Это отнюдь не тривиальная проблема.
Другой подход состоит в том, чтобы создавать различия классов вариантов путем сравнения классов в определенных точках выполнения, и есть такая общая реализация, она использует вывод для вычисления различий: https://github.com/ivan71kmayshan27/ShapelesDerivationExample Я верю, что вы можете найти более простое решение с магнолией. На самом деле это не может работать только для классов, если вы не напишете свой собственный макрос и у вас не возникнут некоторые проблемы с упорядоченными и неупорядоченными коллекциями.
Комментарии:
1. Первое не сработает. API метапрограммирования Java сталкивается со многими вещами в Scala. Даже в Java прокси работают только с интерфейсами, а не с конкретными классами. Я не совсем понимаю, что вы имели в виду под второй частью. Я понимаю, что ОП хочет перехватить вызовы методов, чтобы понять, как развивается значение. Самый простой пример заключается в том, что это не принесет никакой пользы примитивам. Или я неправильно понял ваше замечание?
2. Первое будет работать, потому что код scala преобразуется в байт-код, как и все остальное, и именно поэтому вы можете использовать код scala как из kotlin, так и из java, таким образом, вы можете изменить его с помощью API, который позволяет процессорам байт-кода. Вам все равно придется учитывать некоторые вещи в scala, но говорить «это вообще не сработает» в основном неверно. Второй подход заключается в использовании простых различий в ценностях, а не в шпионаже.
3. Не совсем верно для Scala 3, но да, это выходит за рамки этого вопроса. Я просто уходил от связанной статьи. Я просто пытался сказать, что представленная там методология не может охватить все конструкции Scala. Есть способы сделать это, но это очень быстро выходит из-под контроля.