Шаблонный код в Java/Kotlin - возможно ли?
От: rus blood Россия  
Дата: 16.10.23 15:20
Оценка:
Коллеги, всем привет!

Пишу на котлин, и возникла такая ситуация.
Есть набор разных классов (можно считать, data-классов), одинаковых по структуре, т.е. у них часть полей одинаковы по названиям и типам.
Нужно с объектами этих классов делать однотипные действия с "общими" полями.
На плюсах я бы сделал это шаблонными функциями.
Есть ли аналог шаблонных функций в котлине?

class A {
  int value;
}

class B {
  int value;
}

template <typename T>
void printValue(T t) {
   std::cout << t.value << std::endl;
}

Как подобное изобразить на котлине ?

Почему нельзя вынести одинаковые поля в общий класс?
Классы авто-генерируются по xsd во время сборки.
Файлы xsd берутся с сайта гос-учреждения, корректировать невозможно.
Имею скафандр — готов путешествовать!
kotlin template generics
Re: Шаблонный код в Java/Kotlin - возможно ли?
От: · Великобритания  
Дата: 16.10.23 16:10
Оценка: 5 (1)
Здравствуйте, rus blood, Вы писали:

RB>Почему нельзя вынести одинаковые поля в общий класс?

Это называется duck typing. И во многих ЯП нет такого принципиально. Т.к. это создаёт неявную связь между типами.
Можно размотать через лямбды:
<T> void printValue(Supplier<String> value) {
  System.out.println(value.get());
}
...
var a = new A();
printValue(a::value);
var b = new B();
printValue(b::value);

По классике ООП можно делать адаптеры (удобно в случае если методов больше одного):
interface ValueAdapter
{
  String value();
  
  static ValueAdapter wrap(A a) {return () -> a.value;}
  static ValueAdapter wrap(B b) {return () -> b.value;}
}
void printValue(ValueAdapter adapter) {
  System.out.println(adapter.value());
}
var a = ValueAdapter.wrap(new A());
printValue(a);
var b = ValueAdapter.wrap(new B());
printValue(b);



Можно через рефлексию. Но лучше не нужно.
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Отредактировано 16.10.2023 16:12 · . Предыдущая версия . Еще …
Отредактировано 16.10.2023 16:11 · . Предыдущая версия .
Re: Шаблонный код в Java/Kotlin - возможно ли?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 16.10.23 16:16
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Классы авто-генерируются по xsd во время сборки.


Дописать генератор?
Маньяк Робокряк колесит по городу
Re: Шаблонный код в Java/Kotlin - возможно ли?
От: · Великобритания  
Дата: 16.10.23 16:19
Оценка: 8 (1)
Здравствуйте, rus blood, Вы писали:

RB>Классы авто-генерируются по xsd во время сборки.

RB>Файлы xsd берутся с сайта гос-учреждения, корректировать невозможно.
Ах да, можно ещё подпилить кодогенератор, чтобы проставить нужные интерфейсы. Например https://github.com/highsource/jaxb2-basics/wiki/JAXB2-Inheritance-Plugin
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Шаблонный код в Java/Kotlin - возможно ли?
От: r0nd  
Дата: 16.10.23 18:06
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Почему нельзя вынести одинаковые поля в общий класс?


С точки зрения вашей генерилки на основе XSD-схемы они все-таки разные. Чем обусловлено ваше стремление "подружить" разные классы? Предположу что находятся generated-sources?

RB>Классы авто-генерируются по xsd во время сборки.

RB>Файлы xsd берутся с сайта гос-учреждения, корректировать невозможно.

Их можно локально добавить в resources. Чтобы обеспечить офлайн сборку без прямого соединения (из CI/CD например).

В Kotlin вы можете использовать интерфейсы и обобщенные функции, чтобы достичь подобного поведения, как в вашем примере на C++ с шаблонными функциями. Вам не нужно выносить общие поля в общий класс, и вы можете работать с классами, имеющими общие поля, используя интерфейсы и обобщенные функции.

Следует помнить, что вы будете работать со своими объектами DTO (а не с экземплярами XSD-модели). Таким образом вы сможете дополнительно контролировать, если вдруг XSD-модель внезапмно изменится. В этом случае сборка просто не соберется (потому что мэппинг XSD-in-DTO не найдется) — и это будет сигнал об ошибке.
...<< Dementor 1.4.4 ✪ Lets Play a Game ⚁⚂⚂⚂⚅>>
Re[2]: Шаблонный код в Java/Kotlin - возможно ли?
От: rus blood Россия  
Дата: 16.10.23 20:29
Оценка:
Здравствуйте, ·, Вы писали:

·>Можно размотать через лямбды:

·>По классике ООП можно делать адаптеры (удобно в случае если методов больше одного):

Классов 5 штук, в каждом примерно 10 одинаковых полей.
Много бойлерплейт-кода.
Фактически это не лучше, чем иметь 5 одинаковых функций для каждого класса.

·>Можно через рефлексию. Но лучше не нужно.


Я пробовал, но это бессмысленное решение.
Фактически на вход поступает xml, он парсится в объектную модель авто-сгенерированных классов.
А потом мы читает поля по именам через рефлексию.
Нафига тогда эти классы объектной модели?
Можно было сразу прочитать нужные поля через x-path-ы из xml.
Имею скафандр — готов путешествовать!
Re[2]: Шаблонный код в Java/Kotlin - возможно ли?
От: rus blood Россия  
Дата: 16.10.23 20:30
Оценка:
Здравствуйте, Marty, Вы писали:

M>Дописать генератор?


Это xjc.
Кажется, это спринг, но я подробностей не знаю.
Имею скафандр — готов путешествовать!
Re[2]: Шаблонный код в Java/Kotlin - возможно ли?
От: rus blood Россия  
Дата: 16.10.23 20:31
Оценка:
Здравствуйте, ·, Вы писали:

·>Ах да, можно ещё подпилить кодогенератор, чтобы проставить нужные интерфейсы. Например https://github.com/highsource/jaxb2-basics/wiki/JAXB2-Inheritance-Plugin


Ахаха, это интересно.
Спасибо, завтра поковыряю...
Имею скафандр — готов путешествовать!
Re[2]: Шаблонный код в Java/Kotlin - возможно ли?
От: rus blood Россия  
Дата: 16.10.23 20:39
Оценка:
Здравствуйте, r0nd, Вы писали:

R>С точки зрения вашей генерилки на основе XSD-схемы они все-таки разные.


Верно.
Логически это классы разных документов.
Но у них у всех есть одинаковый набор атрибутов.
Причем, в xsd есть общий базовый тип для них, и часть атрибутов объявлено в базовом типе.
А честь — нет, и хз почему...

R>Чем обусловлено ваше стремление "подружить" разные классы?


Весь этот зоопарк нужно сконвертировать в один класс dto.
Соответственно, с каждым классом чтение одних и тех же полей, одинаковым образом.

При этом, есть еще фишка.
Каждый квартал гос.учреждение выпускает обновление этих xsd.
Фактически, это новая версия и новый набор классов, каждые 3 месяца.
И как минимум одну предыдущую версию нужно поддерживать.

R>Предположу что находятся generated-sources?


Ээээ, наверно.

RB>>Классы авто-генерируются по xsd во время сборки.

RB>>Файлы xsd берутся с сайта гос-учреждения, корректировать невозможно.

R>Их можно локально добавить в resources. Чтобы обеспечить офлайн сборку без прямого соединения (из CI/CD например).


Ну, файлы xsd и выложены в resources.
CI/CD с сайта их не берет.

R>В Kotlin вы можете использовать интерфейсы и обобщенные функции, чтобы достичь подобного поведения, как в вашем примере на C++ с шаблонными функциями. Вам не нужно выносить общие поля в общий класс, и вы можете работать с классами, имеющими общие поля, используя интерфейсы и обобщенные функции.


Звучит, как то, что нужно.
Можете показать пример?

R>Следует помнить, что вы будете работать со своими объектами DTO (а не с экземплярами XSD-модели). Таким образом вы сможете дополнительно контролировать, если вдруг XSD-модель внезапмно изменится. В этом случае сборка просто не соберется (потому что мэппинг XSD-in-DTO не найдется) — и это будет сигнал об ошибке.


Ну, суть функционала в том и состоит, чтобы сконвертировать входное xml-сообщение во внутреннее представление (dto), и не зависеть от формата входных данных.
Имею скафандр — готов путешествовать!
Отредактировано 16.10.2023 20:40 rus blood . Предыдущая версия .
Re[3]: Шаблонный код в Java/Kotlin - возможно ли?
От: r0nd  
Дата: 17.10.23 13:00
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Звучит, как то, что нужно.

RB>Можете показать пример?

Как-то так (ideone):

// Объявляем интерфейс с обобщенными функциями
interface Printable {
    val value: Int
    fun printValue()
}

// Реализуем интерфейс в ваших классах
data class A(override val value: Int) : Printable {
    override fun printValue() {
        println(value)
    }
}

data class B(override val value: Int) : Printable {
    override fun printValue() {
        println(value)
    }
}

fun main() {
    val a = A(42)
    val b = B(123)

    a.printValue() // Выведет значение из A
    b.printValue() // Выведет значение из B
}


В этом примере мы создали интерфейс Printable, который содержит общие поля и функцию printValue(). Затем классы A и B реализуют этот интерфейс, и мы можем вызывать функцию printValue() на объектах обоих классов. Каждый из них будет работать с полем value внутри своего класса.

Такой подход позволяет вам обобщить операции, выполняемые над общими полями в ваших классах, сохраняя при этом индивидуальные особенности каждого класса.
...<< Dementor 1.4.4 ✪ Lets Play a Game ⚀⚀⚂⚃⚄>>
Re[4]: Шаблонный код в Java/Kotlin - возможно ли?
От: · Великобритания  
Дата: 17.10.23 13:29
Оценка:
Здравствуйте, r0nd, Вы писали:

r> В этом примере мы создали интерфейс Printable, который содержит общие поля и функцию printValue(). Затем классы A и B реализуют этот интерфейс,

Ты вопрос не понял. Перечитай начальное сообщение. У него проблема была в том, что A и B — генерённые классы и он их не может менять.

Впрочем, похоже ему подошел вариант поменять кодогенератор.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[5]: Шаблонный код в Java/Kotlin - возможно ли?
От: r0nd  
Дата: 17.10.23 20:26
Оценка:
Здравствуйте, ·, Вы писали:

·>Ты вопрос не понял. Перечитай начальное сообщение. У него проблема была в том, что A и B — генерённые классы и он их не может менять.


Не выдумывай отсебятину Толик, вопрос был про шаблонный код в котлах, я отвечал автору принимая во внимания уже существующие ответы (в том числе и два твоих).

·>Впрочем, похоже ему подошел вариант поменять кодогенератор.


Ну и отлично если ему подошел допотопный метод на основе JAXB. Супер.
...<< Dementor 1.4.4 ✪ Lets Play a Game ⚀⚁⚃⚃⚄>>
Re[6]: Шаблонный код в Java/Kotlin - возможно ли?
От: · Великобритания  
Дата: 17.10.23 20:34
Оценка:
Здравствуйте, r0nd, Вы писали:

r> ·>Ты вопрос не понял. Перечитай начальное сообщение. У него проблема была в том, что A и B — генерённые классы и он их не может менять.

r> Не выдумывай отсебятину Толик, вопрос был про шаблонный код в котлах, я отвечал автору принимая во внимания уже существующие ответы (в том числе и два твоих).
Может быть. Неважно. Просто решение с базовым интерфейсом-классом уж очень очевидное, что вряд ли такое будут спрашивать на форумах.

r> ·>Впрочем, похоже ему подошел вариант поменять кодогенератор.

r> Ну и отлично если ему подошел допотопный метод на основе JAXB. Супер.
Любопытно. А какой есть сейчас современный способ работы с гигантскими моделями? Помню искал не так давно для fpml, ничего более разумного не нашел.
avalon/3.0.0
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re: Шаблонный код в Java/Kotlin - возможно ли?
От: Worminator X Россия #StandWithPalestine 🖤🤍💚
Дата: 05.12.23 06:13
Оценка:
Здравствуйте, rus blood, Вы писали:

RB>Коллеги, всем привет!


RB>Пишу на котлин, и возникла такая ситуация.

RB>Есть набор разных классов (можно считать, data-классов), одинаковых по структуре, т.е. у них часть полей одинаковы по названиям и типам.
RB>Нужно с объектами этих классов делать однотипные действия с "общими" полями.
RB>На плюсах я бы сделал это шаблонными функциями.
RB>Есть ли аналог шаблонных функций в котлине?

В базовой Java есть шаблонные функции:
import java.lang.reflect.Field;

public class Program {
    static <T> void printValue(T t) throws Exception {
        final Field field = t.getClass().getDeclaredField("value");
        final String value = (String)field.get(t);
        System.out.println(value);
    }
    static class A {
        public String value;
    }
    static class B {
        public String value;
    }
    public static void main(String[] args) {
        final A a = new A();
        a.value = "A";
        final B b = new B();
        b.value = "B";
        try {
            printValue(a);
            printValue(b);
        } catch (Exception ex) {
            System.err.println(ex.getMessage());
        }
    }
}


Но архитектурно правильно, как уже сказали, создавать специальный класс-адаптер.
В Scala для шаблонных функций есть trait'ы, имеются ли они в Kotlin, не знаю.
Как запру я тебя за железный замок, за дубовую дверь окованную,
Чтоб свету божьего ты не видела, мое имя честное не порочила…
М. Лермонтов. Песня про царя Ивана Васильевича, молодого опричника и удалого купца Калашникова
Отредактировано 05.12.2023 6:19 Worminator X . Предыдущая версия .
Re: Шаблонный код в Java/Kotlin - возможно ли?
От: vsb Казахстан  
Дата: 05.12.23 06:22
Оценка:
В данном случае копипаста это лучший вариант.

Может быть будет уместно использовать статическую перегрузку, если это сделает код читаемей в другом месте:

static int value(A a) { return a.value; }
static int value(B b) { return b.value; }
Отредактировано 05.12.2023 6:26 vsb . Предыдущая версия . Еще …
Отредактировано 05.12.2023 6:23 vsb . Предыдущая версия .
Re[2]: Шаблонный код в Java/Kotlin - возможно ли?
От: GarryIV  
Дата: 22.01.24 22:49
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Может быть будет уместно использовать статическую перегрузку, если это сделает код читаемей в другом месте:


vsb>
vsb>static int value(A a) { return a.value; }
vsb>static int value(B b) { return b.value; }
vsb>


в обратную сторону видел делают (экстеншныы в котдине) а в эту то сторону зачем?
WBR, Igor Evgrafov
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.