有人能解释一下这个学科中提到的(子)类的存在吗?
_
Rational::constants false
# [:compatible]
Rational::compatible
# NoMethodError: undefined method 'compatible' for Rational:Class
Rational::const_get 'compatible'
# NameError: wrong constant name compatible谢谢。
发布于 2016-02-21 00:19:03
我相信这个类的存在是为了向后兼容Ruby的旧版本。换句话说,它使Marshal.load能够在一个版本的Ruby中加载复杂和Rational对象,这些对象是在一个旧版本的Ruby中封送的。
您可以看到第二行(rational.c)中定义了Rational::兼容类的位置:
rb_define_private_method(rb_cRational, "marshal_dump", nurat_marshal_dump, 0);
compat = rb_define_class_under(rb_cRational, "compatible", rb_cObject);
rb_define_private_method(compat, "marshal_load", nurat_marshal_load, 1);
rb_marshal_define_compat(rb_cRational, compat, nurat_dumper, nurat_loader);我的C语言很糟糕,但在我看来,这四行代码分别做了以下工作:
Rational#marshal_dump私有方法定义为指向C函数nurat_marshal_load的指针。compatible类下的Rational类(rb_cRational)。我认为第三个论点,rb_cObject是超类。Rational#marshal_load定义为C函数nurat_marshal_dump。rb_marshal_define_compat:Rational类(rb_cRational);Rational::兼容类(compat);以及nurat_dumper和nurat_loader。从第1 629项开始,在同一个文件中,您可以看到定义nurat_dumper和nurat_loader (以及nurat_marshal_dump和nurat_marshal_load)的位置。使用git blame的魔力,我们可以确切地看到何时定义了nurat_dumper和nurat_loader:2012年7月25日,在Subversion提交#36538中。以下是提交消息:
Compos.c,理性主义.c:兼容的编组装载机
complex.c,rational.c:兼容的编组加载器,兼容1.8。红宝石-核心:45775现在我们有进展了!Bug #6625是这样的一个:
复杂理性的断裂元帅相容 1.8或更早版本的复杂和Rational不能由主干加载。
它接着描述了一个测试用例,并包括在上面提交中看到的修补程序。
那么,也许你在想,rb_marshal_define_compat是什么呢?你可以看到它,marshal.c。就像我说的,我的C语言很糟糕,但我认为它所做的是把它的论点--newclass(即Rational)、oldclass (Rational::兼容)、dumper和loader-into a 结构 --并插入到compat_allocator_tbl中。稍后,当您尝试Marshal.dump或Marshal.load对象时,它将查看该表中是否存在兼容性类,并在必要时使用它的"dumper“或”加载程序“。
至于为什么Rational::兼容性不是用大写字母命名的,也不能通过普通方式访问的,我只能猜测这是通过设计实现的,因此只能通过Ruby在内部进行访问。
但是,您可以使用ObjectSpace获得对类的引用,尽管您不能使用它做很多事情:
compatible = ObjectSpace.each_object(Class).find do |o|
o.name == "Rational::compatible"
end
p compatible
# => Rational::compatible
p compatible.instance_methods(false)
# => []
p compatible.private_instance_methods(false)
# => [:marshal_load]https://stackoverflow.com/questions/35528864
复制相似问题