func SumIntsOrFloats[K comparable, V int | float64](m map[K]V) V {
var s V
for _, v := range m {
s += v
}
return s
}
比如上面这段代码? v 表示的是两种类型。 但是 java/kotlin 里面好像只有上限和下限。
fun <T : File> getString(uri: T): T {
return uri
}
kotlin 里面的 T ,类型只有一种,感觉是真的不方便? 各位大神,kotlin 或者 java 有没有其他的写法支持多种类型?
1
Rocketer 2022-12-25 01:07:46 +08:00 via iPhone
只有弱类型语言才可能这样,比如 TypeScript 也可以。
强类型语言的优势就是强类型,不方便只是你不习惯,并不是弱点。 |
3
Trim21 2022-12-25 01:34:38 +08:00
@jeesk #2
golang 的泛型也不一定能表示多个类型,你的例子是基础类型,用到的也只是 + ,所以可以这样写。 但如果换成 struct 的话就不行了 type T1 struct { } func (t T1) Close() error { return nil } type T2 struct { } func (t T2) Close() error { return nil } 这个可以编译 var _ io.Closer = T1{} var _ io.Closer = T2{} 但这个泛型函数没法编译 func CanNotCompile[T T1 | T2](t T) error { return t.Close() } |
4
TWorldIsNButThis 2022-12-25 01:34:49 +08:00
overload
|
5
GeruzoniAnsasu 2022-12-25 02:37:15 +08:00
@Trim21 可以绕:
type typeProxy interface { Close() error } func CanCompile[T T1 | T2](t T) error { return any(t).(typeProxy).Close() } CanCompile(T3{}) // 拒绝编译 -------- java 的泛型系统的「类型限制」( constraint )只能指定类型继承链上的上下界,泛型容器或泛型方法仅仅是把对象的类型自动向上转换而已,因此不可能指定不在同一继承链上的两个任意类型的组合类型( T | U ),设想 (T|U) t; t.Method(); 此时 t 的类型只能协变为 Object ,而 Object 不会有 Method()方法。 这跟强弱类型语言没什么关系,跟泛型系统的实现和设计有关,只能说,java 就这样,你想实现接近的效果,有非泛型的写法( instanceof ) |
6
Leviathann 2022-12-25 02:54:26 +08:00
java 没有或类型,要表达同一个意思,就是用重载
|
7
pennai 2022-12-25 04:09:42 +08:00
c++可以
|
8
kakach 2022-12-25 06:50:06 +08:00 via Android 1
|
9
BBCCBB 2022-12-25 09:27:38 +08:00
interface/abstract, 比如(Number t), t 可以传 int, float, double, long 等, 不过必须子类实现父类才行,,
不能像 go 这样直接指定多个. |
10
jeesk OP @GeruzoniAnsasu 所以 java 的泛型是假的, 语法糖😅
|
11
ZSeptember 2022-12-25 09:35:01 +08:00 3
不是一句假的这么简单。。
泛型有很多种实现方式,CPP 的基于模板的,Go 也类似基于模板的,Java 是基于类型擦除的,各有优劣。 而且,不支持 union type ,只是语言层的问题,和泛型实现没什么关系,有需要的话,Java 也可以支持。 |
12
coala 2022-12-25 10:52:51 +08:00
Java 的泛型是假的. class 文件反编译后你就看到了,new ArrayList<String>() 反编译后是 new ArrayList(), 其他语言的是怎么实现的不清楚, 但是 Java 算是比较取巧的方式吧, 大概只有编译时检查泛型, 实际上最下面还是 object
|
13
iseki 2022-12-25 10:54:04 +08:00 via Android
不支持联合类型,和泛型其实没太大关系,你看 ts 不用泛型也能联合类型。语言设计问题,可能和 Java 是名义类型有点关系,也许联合类型这种情况下不太好实现?
|
14
iseki 2022-12-25 10:57:07 +08:00 via Android
至于类型擦除…Java 这种实现的好处是代码不膨胀,和旧的兼容,运行时也没额外消耗,坏处就是运行时不一定能拿到泛型信息
|
15
coala 2022-12-25 11:01:28 +08:00
感觉这就和茴的几种写法一样.. 泛型是为了什么呢, 如果是为了统一类型, 一个 ArrayList 你说允许有两种类型. 我这写了几年 Java 的脑回路反而有点不适, 无法就是在灵活和规整直接做取舍
|
16
jeesk OP @coala 少写代码。 比如别人的接口参数就是 object 类型, 支持的就是 string 或者 int 类型,我要限制类型, 这个时候我要写 2 个方法分别是 stringh 和 int 的类型, 少写点代码就少写。
|
18
iseki 2022-12-25 11:07:46 +08:00 via Android
@jeesk 我觉得你举的这个例子用 union type 不太好,overload 更合适。你写了个 string | int ,里面还是要 is string is int 分别去处理
|
20
iseki 2022-12-25 11:10:15 +08:00 via Android
噢,我懂了,你是额外在人家的接口上加了个约束
|
22
coala 2022-12-25 11:49:45 +08:00
@jeesk 第一次写 node.js 的时候, 当时实现了一个简单 WebSocket Server, node.js 居然只用 1 个文件 20 多行代码就搞定了, Java 干这个事得定义了好几个对象, 几个文件配合干, 代码很容易一大片。 对我来说非常震撼。
Java 现在只在编译时检查一个泛型, 看上去实现检查 2 个泛型也不是什么难事, 兼容旧版这种理由我是不信的, 编译时能检查一个也能检查两个 , 反正是 "假泛型"。 我更倾向于作者就是觉得只允许一个类型更好一点。 像 Python 强制 4 个空格的语法, 咱也不敢骂。 没有泛型好, 还是只有一种类型好, 还是支持多种类型好, 真的有答案吗? |
27
Huelse 2022-12-25 13:51:41 +08:00
可能 Scala3 更符合你的需求,如 Intersection Types, Union Types 等等 https://dotty.epfl.ch/
|
28
lisongeee 2022-12-25 13:55:58 +08:00
kotlin 可以通过密封类实现联合类型类似效果,但是不如 typescript 灵活
|
30
netabare 2022-12-27 08:38:50 +08:00 via Android 1
这个是 sum type ,typescript 里面有不错的支持。kotlin 和 java 都没有,得用 scala ,不然就是纯 fp 的 ocaml 、haskell 之类的语言才有了。
sealed class 模拟的问题在于不能用再已有的类型上,必须手写一层例如 IntWrapper 、StringWrapper 之类的层来套着,对数据互转很不方便。 |