为什么Rust允许标识符多重定义?同名变量与类型可共存
为什么Rust允许变量和类型同名不冲突
这是因为Rust内置了两套完全独立的命名空间,类型和值的符号分开存储、查找时互不干扰:
- 类型命名空间:存储所有struct、enum、trait、自定义类型别名这类和类型相关的符号
- 值命名空间:存储所有变量、函数、常量、静态变量这类和值相关的符号
你代码里写的let Vec = 1.;只是在值命名空间新增了一个名为Vec的f64变量,完全不会改动类型命名空间里标准库定义的Vec结构体,二者从始至终都是共存的。
不同的使用场景会自动匹配对应的命名空间:
- 直接把标识符当值用的时候(比如
println!("{}", Vec);里的Vec),只会查找值命名空间,所以拿到的是你定义的f64变量 - 用
::调用关联项的时候(比如Vec::from、Vec::new),路径前缀只会查找类型命名空间,所以找到的还是标准库的Vec结构体,和你定义的变量没有任何关系。
注意这和同一个命名空间里的变量遮蔽不是一回事:变量遮蔽是后定义的同名单词覆盖了之前的定义,旧的定义无法再访问;而这里两个同名符号属于不同空间,全程都可以在对应场景下正常使用。
调用Vec.test()时会执行哪个类型的方法
方法调用的语法表达式.方法名()有固定的查找规则:先对方法名前面的表达式求值,拿到这个值的实际类型之后,再匹配对应类型的方法实现。
你写的Vec.test()里,Vec作为表达式首先会去值命名空间查找,拿到的是你定义的f64类型的变量,所以会执行f64类型实现的test()方法。
如果你想要调用Vec结构体的test()方法,根据方法类型有两种写法:
- 如果是关联方法:直接用
Vec::test(参数列表)调用,::前缀会匹配类型命名空间的Vec结构体 - 如果是实例方法:构造
Vec结构体的实例后再调用,比如Vec::new().test()
内容的提问来源于stack exchange,提问作者null
相关产品推荐
相关产品推荐

