Имя: Пароль:
IT
Веб-мастеринг
Дженерики (обобщения в джаве)
Ø (Волшебник 23.11.2023 19:41)
0 Брат по разуму
 
23.11.23
14:01
Добрый день!
Я знаю, у нас есть те кто рубит в джаве. Хочу написать учебный пример сложить 2 + 2 при этом написать обобщенный метод, который принимает любые типы. Возможно ли это? Вот пример кода
public class App {

    public static void main(String[] args) {
        Point pt = new Point<>(2, 2);        
        System.out.println(pt.getSum());
    }
}

class Point<T extends Number>{
    public T x,y;
    Point(T x, T y){
        this.x = x;
        this.y = y;
    }
    T getSum() {
        return sum(x,y);
        return x + y; // ошибка! The operator + is undefined for the argument type(s) T, T
    }
}
1 Брат по разуму
 
23.11.23
14:03
я думал оно метод sum унаследует. Но тоже ошибка.
return sum тоже ошибка
2 Волшебник
 
23.11.23
14:03
Напишите так: 2+2
и не любите мозги
3 Garykom
 
гуру
23.11.23
14:12
Point pt = new Point<>(2, 2); // - почему тип в <> не указал?
4 Garykom
 
гуру
23.11.23
14:14
return x.doubleValue() + y.doubleValue();
5 Брат по разуму
 
23.11.23
14:21
(4) А если 2 это Integer?
6 Garykom
 
гуру
23.11.23
14:22
(4)+ хотя еще привести к T желательно
return (T)(x.doubleValue() + y.doubleValue());
7 sikuda
 
23.11.23
14:22
(5) А если 2 это "2"?
8 Garykom
 
гуру
23.11.23
14:23
(7) extends Number
9 Брат по разуму
 
23.11.23
14:25
я вообще, что хотел. Написать в качестве учебного примера, обобщенный метод, который принимает любой числовой тип(Integer,Double,Float) и возвращает сумму. Или такое не возможно?
10 sikuda
 
23.11.23
14:27
(0) Зачем нужны дженерики? Чтобы выдавать ошибки программисту на этапе сборки! Сказать нерадивому, что он не для всех нужных типов переопределил операцию + ;)
11 Garykom
 
гуру
23.11.23
14:30
(9) Можно.
Можно даже для любых типов (например строки складывать или массивы/списки/объекты)
Но через instanceof придется
12 Брат по разуму
 
23.11.23
14:32
(10) я думал, чтобы 1 метод писать вместо 3х.
13 Garykom
 
гуру
23.11.23
14:33
(12) для числовых хватит одного (6)
для прочих приводить и отдельные подметоды реализовать и вызывать после приведения
14 Брат по разуму
 
23.11.23
14:34
(11) кинь пример кода пожалуйста. У меня это навязчивая идея, кушать не могу.
15 Garykom
 
гуру
23.11.23
14:38
(14) У тебя код в (0) только замени "return x + y;" на (6)
и удали "return sum(x,y);"
16 Брат по разуму
 
23.11.23
14:41
public class App {

    public static void main(String[] args) {
        Point pt = new Point<>(2d, 2d);        
        System.out.println(pt.getSum());
    }
}

class Point<T extends Number>{
    public T x,y;
    Point(T x, T y){
        this.x = x;
        this.y = y;
    }
    T getSum() {
        return (T)  (x.doubleValue() +  y.doubleValue());
    }
    
    
}
cannot cast from double to T
17 Брат по разуму
 
23.11.23
14:43
ну и опять же, а если тип будет Integer, тогда нужно второй метод писать,
getSumInt() {
   return x.doubleValue() + y.doubleValue()
18 Брат по разуму
 
23.11.23
14:46
В общем суть какая. Как в java или С# написать обобщенный метод, который принимает любой числовой тип и возвращает сумму. Или это не возможно? И эти обобщения они только для коллекций типа ArrayList<String>
19 Garykom
 
гуру
23.11.23
14:52
(16) а если просто
return x.doubleValue() + y.doubleValue();

тоже ругается?
20 Garykom
 
гуру
23.11.23
15:02
(17) в общем случае да
придется на каждый из классов Byte, Double, Float, Integer, Long и Short ваять свой подметод и вызывать его
21 Брат по разуму
 
23.11.23
15:05
(20) не, тогда проще перегрузку методов использовать.
22 Garykom
 
гуру
23.11.23
15:07
(21) Проще использовать только один тип
Только не говори что свою платформу 1С сам на java решил написать
23 Garykom
 
гуру
23.11.23
15:10
(21) Может ты меня не совсем понял?
Я то про то что можно реализовать один внешний T getSum()
Но внутри придется делать условия через
if (x instanceof Integer){
// ...
} else if (x instanceof Float){
// ...
} else ...
24 K1RSAN
 
23.11.23
15:11
С джавой не работал, но в шарпе задачка известная.
Point pt = new Point<>(2, 2);  - у тебя не указан тип Т, что у тебя там. Ты хочешь, чтобы программа сама определяла, какого типа у тебя данные?

new Point<> - вот здесь в <> по сути ты должен указать, какой тип у данных, которые ты хочешь ввести.
Либо придумать логику, по которой программа должна определить тип данных
25 Garykom
 
гуру
23.11.23
15:14
(24) кстати да
может поэтому и ругается cannot cast from double to T
что не понимает как double конвертнуть в неизвестный T

что он забыл T внутри <> уже (3)
26 novichok79
 
23.11.23
15:18
(0) зачем вам это? типа в учебных целях? лучше делайте пет-проект, учите внутрянку джавки.
а еще лучше шарпы, они посвежее.
я 2,5 года назад обманом прошел собес на middle Java разраба, дали ЗП 270 тыр.
но мне Java не очень просто, да и побоялся что не потяну.
27 Новиков
 
23.11.23
15:30
(0) Теперь Вы понимаете, за что джавистам платят 0.5 млн. рублей в месяц на руки?
28 Брат по разуму
 
23.11.23
15:31
(24) так то работает

public class App {

    public static void main(String[] args) {
        Point pt = new Point<Double>(2d, 2d);
        pt.getSum();
    }
}

class Point<T extends Number>{
    public T x,y;
    Point(T x, T y){
        this.x = x;
        this.y = y;
    }
    Double getSum() {
        return x.doubleValue() + y.doubleValue();
    }    
    
}
но а если я напишу
Point pt = new Point<Integer>(2d, 2d); - то сломается.
29 Garykom
 
гуру
23.11.23
15:34
(28) а ты пробовал?
30 Брат по разуму
 
23.11.23
15:34
(24) выложи код из С# пожалуйста. обобщенный метод, который принимает любой числовой тип и возвращает сумму.
31 Garykom
 
гуру
23.11.23
15:35
(29)+ как раз на этот случай я и хотел в (6) привести обратно к T
32 Uberschall
 
23.11.23
15:35
(24) тип T не обязательно явно указывать. Может применяться вывод типов.
(23)это хреновое решение. не по солиду. Представь что потом добавят наследника для Number, тогда это решение не будет работать
(0) смотри контракт на базовый интерфейс и исходи из него.
33 Garykom
 
гуру
23.11.23
15:36
(31)+ хотя ты же просто вызваешь pt.getSum();
так что пофиг ну да на входе int а вернет double и что?
34 Брат по разуму
 
23.11.23
15:36
(29)
public class App {

    public static void main(String[] args) {
        Point pt = new Point<Integer>(2, 2);
        System.out.println(pt.getSum());
    }
}

class Point<T extends Number>{
    public T x,y;
    Point(T x, T y){
        this.x = x;
        this.y = y;
    }
    Double getSum() {
        return x.doubleValue() + y.doubleValue();
    }    
    
}
не не сломался, но преобразовал к double. Это не совсем то, что я хотел.
35 Garykom
 
гуру
23.11.23
15:37
(32) >это хреновое решение

чтобы не потерять точность же
а то если пару long сложить через double а потом обратно в long я уже не помню их разрядность
36 Garykom
 
гуру
23.11.23
15:39
(34) зачем
Double getSum() {
        return x.doubleValue() + y.doubleValue();
}

вместо
T getSum() {
        return x.doubleValue() + y.doubleValue();
}
37 Uberschall
 
23.11.23
15:40
(0) еще вопрос, что будет если у тебя тип Point будет явно указан как Number, а фактически в конструктор будут переданы и int и double (если в int-овой размерности прибавить double, то произойдет переполнение)?
Еще туда же почитай про ковариантность и инвариантность.
38 Брат по разуму
 
23.11.23
15:41
(36) Type mismatch: cannot convert from double to T
39 Uberschall
 
23.11.23
15:41
(35) причем тут точность, если у тебя неизвестный список реализаций? как ты сделаешь if esle на неограниченный список?
40 Garykom
 
гуру
23.11.23
15:42
(38) ну придумай как конвертировать ))
41 Garykom
 
гуру
23.11.23
15:42
(39) для неизвестных просто ветка else
42 Garykom
 
гуру
23.11.23
15:43
(41)+ хотя согласен что опираться надо на базовые типы
43 Uberschall
 
23.11.23
15:43
(41) и что вернет для неизвестных? скорее всего не то, что ожидает получить тот, кто соберется воспользоваться этим методом...
44 Garykom
 
гуру
23.11.23
15:45
(43) Так а что можно вернуть для неизвестного еще класса?
Для родительских классов instanseof отработает прекрасно
45 Arbuz
 
23.11.23
15:53
Как это 'который принимает любые типы'?
А если один аргумент будет long, а другой double, что надо с ними делать?
А если строка и вектор?
46 Garykom
 
гуру
23.11.23
15:57
(45) а это уже выходит за рамки задачи (0)
у ТС оба аргумента одного типа T
47 Garykom
 
гуру
23.11.23
15:59
Интересно сработает ли

T getSum() {
    if(x instanceof Double || y instanceof Double) {
        return x.doubleValue() + y.doubleValue();
    } else if(x instanceof Float || y instanceof Float) {
        return x.floatValue() + y.floatValue();
    } else if(x instanceof Long || y instanceof Long) {
        return x.longValue() + y.longValue();
    } else {
        return x.intValue() + y.intValue();
    }
}
48 Брат по разуму
 
23.11.23
16:12
(47) везде ошибка Type mismatch: cannot convert from double to T
49 Брат по разуму
 
23.11.23
16:13
(45) ну я и спрашиваю, можно ли написать такой метод с помощью механизма обобщений или нет?
50 Брат по разуму
 
23.11.23
16:14
+(49) хочу понять возможности этих обобщений. Что они могут, а что нет. Как то маловато в книгах и интернете таких примеров. Вернее вообще нет.
51 Брат по разуму
 
23.11.23
16:27
https://translated.turbopages.org/proxy_u/en-ru.ru.a7386657-655f52b0-0c54ff2b-74722d776562/https/stackoverflow.com/questions/58509727/generalized-method-to-get-sum-of-any-data-type-in-java

наверное нельзя, иначе бы классы BigInteger, BigDouble,BigFloat не писали бы, а написали бы один BigNumber и он бы любой тип данных принимал.
52 Брат по разуму
 
23.11.23
16:29
тьфу нет таких класов как BigDouble и BigFloat есть только BigDecimal. Ну значит не писали бы BigInteger и BigDecimal, а написали бы один класс.
53 Arbuz
 
23.11.23
16:38
(46) Ну, так ясно же сообщается
The operator + is undefined for the argument type(s) T, T
Либо приводить типы, либо определить логику '+' над типом Т
(49) Для того чтобы написать какой-то метод необходимо чётко представлять 'такой' это какой конкретно.

Вот, кстати, такое отсутствие понимание роднит кодлу пограммистов 1С с джавистами. До такого количества тормозного говнокода как на жабе, 1С ещё пахать и пахать.
54 Брат по разуму
 
23.11.23
16:40
(53) в С++ это можно сделать 3мя способами
https://qaa-engineer.ru/kak-napisat-metod-klass-kotoryj-by-odinakovo-rabotal-so-vsemi-chislovymi-tipami/
55 Garikk
 
23.11.23
17:06
(52) никто не мешает написать BigNumber, но это неявно маскирует ограничения Integer и Decimal и ведет за собой всякие ошибки
вообще если так думать то вы к питончику придете, а то и в js ;) там всё в одну кучу
56 Garikk
 
23.11.23
17:07
что будет если Decimal+Integer сложить? а если BigNumber(Integer) + BigNumber(Decimal) ?
57 Garikk
 
23.11.23
17:07
вот чтобы разночтений не было, так в базовом фреймворке языка не делают, но ты сам можешь это сделать
58 Бертыш
 
23.11.23
19:14
Хм. Бывает что и коту делать нечего
59 Волшебник
 
23.11.23
19:42
Давайте уже закроем эту тему. Мне противно на это смотреть ещё с момента (2)