你真的了解范型么?

572 阅读4分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.什么是范型?

泛型字面理解“广泛适用的类型”,其本质是指类型参数化,即可以将类型当作参数传递给一个类或者是方法。 允许在定义类、接口、方法时使用类型形参,分别称为泛型类、泛型接口、泛型方法,当使用时 指定具体类型。 所有使用该泛型参数的地方都被统一化,保证类型一致。

范型是不是看着像弱类型? 两者是有着本质区别的,弱类型是对编译系统说:这个变量什么类型都可以,你自己看着办吧!就像js,不指定类型; 而范型是对编译系统说:这个变量按说好的来,说这次是啥类型这个变量就是啥类型。

2.为什么要用范型?

参数化多态(Parametric Polymorphism),根据实参生成不同的版本,支持任意数量的调用,即泛型,简言之,就是把元素类型变成了参数。 使用范型可以优化我们的代码。

**不明白?**哪里优化代码了?举个荔枝^_^

#这里是java的Map类的范型定义
/**
 * An object that maps keys to values.  A map cannot contain duplicate keys;
 * each key can map to at most one value.
 * ...
 * @param <K> the type of keys maintained by this map
 * @param <V> the type of mapped values
 * ...
 */
public interface Map<K,V> {
   ...
   V put(K key, V value);
   ...
   V get(Object key);
   ...
}
#如果没有范型呢?
public interface StrMap {
   ...
   String put(String key, String value);
   ...
   String get(String key);
   ...
}
...
public interface IntegerMap {
   ...
   Integer put(Integer key, Integer value);
   ...
   Integer get(Object key);
   ...
}
#所有的类型全部穷举一遍,又累又冗余,万一要改是不是要疯?

或者像下面这样:

nofanx.gif

3.Golang没有范型不是一样用么?

Go是一门强类型语言,意味着程序中的每个变量和值都有某种特定的类型,例如int、string等。没有泛型,很多人以此“鄙视”Golang。而目前由于泛型支持的复杂性,Golang的设计和实现者并没有把这个泛型支持作为紧急需要增加的特性 而是建议大家使用接口来实现类似范型的功能。很多人因此而十分不满,认为没有泛型增加了很多工作量。 好消息是Go1.17中已经发布了泛型的体验版,这一功能也是为1.18版本泛型正式实装做铺垫。

Golang1.17中泛型的要点

  1. 函数可以通过type关键字引入额外的类型参数(type parameters)列表:func F(type T)(p T) { ... } 。
  2. 这些类型参数可以像一般的参数一样在函数体中使用。
  3. 类型也可以拥有类型参数列表:type M(type T) []T。
  4. 每个类型参数可以拥有一个约束:func F(type T Constraint)(p T) { ... }。
  5. 使用interface来描述类型的约束。
  6. 被用作类型约束的interface可以拥有一个预声明类型列表,限制了实现此接口的类型的基础类型。
  7. 使用泛型函数或类型时需要传入类型实参。
  8. 一般情况下,类型推断允许用户在调用泛型函数时省略类型实参。
  9. 如果类型参数具有类型约束,则类型实参必须实现接口。
  10. 泛型函数只允许进行类型约束所规定的操作。
#例如:原来的加法函数
func Add(i1, i2 int) int
func AddFloat(i1, i2 float) float
#golang 下的范型定义:
func Add[T any](i1, i2 T) T

4.泛型困境

泛型和其他特性一样不是只有好处,为编程语言加入泛型会遇到需要权衡的两难问题。语言的设计者需要在编程效率、编译速度和运行速度三者进行权衡和选择,编程语言要选择牺牲一个而保留另外两个。 在2009年的时候,Russ Cox提出来的一个关于泛型的问题叫做泛型困境,用来收集人们对Golang中泛型的一些意见和建议,对Golang泛型设计当中的问题进行解释,并表示他们并不急于去实现泛型,因为还没有找到一个合适的实现方案去解决困境。 而泛型困境的本质是,关于泛型,你想要缓慢的程序员、缓慢的编译器和臃肿的二进制文件,还是缓慢的执行时间。简单来说就是:要么苦了程序员,要么苦了编绎器,要么降低运行时效率。

fanxkunj.png

5.传送门

终于!12年后Golang支持泛型了!

一文通关java范型