如何使自定义Ruby类型表现得像字符串?

Fre*_*abe 3 ruby

如果我有一个表示某种字符串类型的自定义Ruby类,就像在

class MyString
end
Run Code Online (Sandbox Code Playgroud)

我应该实现哪些功能才能使以下用例成为可能:

  1. 每当MyString期望时传递Ruby字符串
  2. MyString每当一个Ruby字符串被传递时传递一个
  3. 将Ruby字符串与MyString值进行比较(无论我使用s == t或是否都无关紧要t == s).

我见过这样有趣的各种功能to_s,cmp,==eq了,但他们每个人叫时,它不是我清楚.

我的具体用例是我正在使用C API编写一个Ruby扩展,它公开了获取(并返回)自定义字符串类型(QString确切地说)的值的函数,我的扩展也会注册这些值.但是,我想让这些自定义字符串尽可能直观.不幸的是,我不能只从我的C代码返回Ruby字符串,因为它应该可以在字符串上调用Qt方法.

Dig*_*oss 6

至少有三种方法:

  1. class MyString < String; ...; end
  2. 限定 #to_s
  3. 限定 #to_str

同时执行#2和#3将使对象非常像真正的String,即使它不是子类.

#to_s是一个显式转换器,这意味着它必须出现在Ruby代码中才能工作.

#to_str是一个隐式转换器,这意味着Ruby解释器会在需要String时尝试调用它,但是会给出其他内容.

更新:

以下是您可以享受的一些乐趣的示例to_str:

begin
  open 1, 'r'
rescue TypeError  => e
  p e
end
class Fixnum
  def to_str; to_s; end
end
open 1, 'r'
Run Code Online (Sandbox Code Playgroud)

运行时,第一次打开失败,TypeError但第二次打开继续寻找1.

#<TypeError: can't convert Fixnum into String>
fun.rb:9:in `initialize': No such file or directory - 1 (Errno::ENOENT)
    from fun.rb:9:in `open'
Run Code Online (Sandbox Code Playgroud)