有一些Ruby类不允许在它们的示例上定义单例方法,例如Symbol
:
var = :asymbol
def var.hello
"hello"
end
# TypeError: can't define singleton method "hello" for Symbol
- 我认为这可能是对所有立即数的限制,但它似乎适用于
nil
、true
和false
*(但不适用于Fixnum
或Bignum
的示例):
var = true
def var.hello
"hello"
end
var.hello #=> "hello"
我不明白为什么Ruby允许在某些对象类上定义单例方法,而在其他对象类上却不允许。
2条答案
按热度按时间gt0wga4j1#
这与Matz在这里描述的“立即值”概念有关。
实际上,立即值不允许使用单例方法,但是,在
true
、false
和nil
的情况下,实际上存在支持这些值的单例类(或者值实际上是单例类--我不确定这一点)因此,您可以向后台类添加单例示例,使其表现为值本身。Numeric和Symbol示例不是单例(很明显),没有地方容纳单例方法。vh0rcniy2#
目前(
ruby-3.2.1
)还不能为整数、浮点数、符号和冻结字符串定义单例方法(我也用ruby-2.6.10
确认了这一点):代码的相应部分如下所示:
现在,让我们看看
TYPE
的功能:rb_type()
:信息量很大,我先给你们一些常数:
和一些类型常量:
那么,什么是即时价值呢?
RB_IMMEDIATE_P
:RB_SPECIAL_CONST_P
:代码中的名称似乎有点误导,但下面的方式或多或少是有意义的。立即值是设置了3个最低有效位中的任何一个和
RUBY_Qfalse
的值。一些立即值是常量,如nil
(0x04
),false
(0x00
),true
(0x14
).有些只是内联存储值(或者至少不指向某个地方),比如fixnums(整数),flonums(浮点数)和静态符号。RB_FIXNUM_P
(是否为修复号?):RB_FLONUM_P
(是否为氟?):RB_STATIC_SYM_P
(是否为静态符号?):RB_BUILTIN_TYPE
(返回指针指向的值的非立即数类型):RBASIC
(类型转换为struct RBasic*
,这是一个符合任何VALUE
的结构体,不是指针):那么
FL_TEST_RAW(obj, RSTRING_FSTR)
呢?这是一种检查字符串是否冻结的方法。现在,实际上一些整数、浮点数和符号是以指针的形式存储的,这就是为什么我对每种类型都进行了两次检查:
1
(立即数)和1000000000000000000000
(指针),1.0
(立即数)和1e100
(指针),:sym
(立即数)和:"sym#{v}"
(指针,动态符号)。在ruby-2.6
中,区别更为明显。至于为什么你可以给
nil
添加方法,而不能给整数添加方法?难倒我了:)很可能是因为nil
是一个,而整数有很多。目前,由ruby
来选择是内联还是在对象中存储一个值。如果你可以给整数、浮点数和符号添加单例方法,那么ruby
将被迫把它们存储为对象(那些有额外方法的对象)。这就消除了优化。可能被认为弊大于利。顺便说一下,
-'string'
是一个冻结的字符串。