Ruby中force_encoding为何未命名为force_encoding!?
关于Ruby
force_encoding 命名的疑问解答 这个问题戳中了Ruby命名惯例里特别容易混淆的点——确实,咱们平时默认带!的方法是修改自身(原地突变),不带的返回副本,force_encoding看起来完全反着来,刚接触的时候真的会懵。
其实这里的关键是Ruby对「破坏性修改(destructive modification)」的定义:
- Ruby里的
!方法,针对的是改变了对象核心内容/数据结构的操作。比如gsub!会直接替换字符串的字节内容,sort!会重新排列数组的元素顺序,这些都是实打实改变了对象的“值”。 - 而
force_encoding做的事情,只是修改了字符串对象携带的编码元数据——也就是告诉Ruby“你以后要按这个编码来解读我身上的字节”,但字符串的字节本身从头到尾没有任何变化。
举个直观的对比例子:
- 用
encode!('GBK')的时候,Ruby会把原字符串的UTF-8字节转换成GBK字节,字节序列变了,这是真·修改,所以带!; - 用
force_encoding('GBK')的时候,Ruby只是换了个解读方式,字节还是原来的UTF-8字节,只是现在按GBK来读(大概率会出现乱码,但字节本身没动),所以不算“破坏性修改”,也就不用加!。
另外还有个类似的例子:freeze方法会把对象改成不可变状态,也是修改了对象的属性,但同样不带!——因为它没改变对象的核心内容,只是调整了它的可修改状态。
所以这不是命名不一致,而是Ruby的命名惯例里,!的判定标准是是否改变了对象的实际内容,而不是是否修改了对象的任何属性。force_encoding只是调整解读规则,没碰内容,所以才用了不带!的命名。
内容的提问来源于stack exchange,提问作者Magne
相关产品推荐
相关产品推荐

