大佬教程收集整理的这篇文章主要介绍了模仿另一个Ruby类,所以对象通过===类型检查,大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
有各种各样的用例.在Fixnum的情况下,我想定义一个更具体的整数类型,它本质上是一个Fixnum,但也实现了一些额外的逻辑.我不能子类Fixnum本身,因为立即类型如Fixnum和Symbol不能被子类化.@H_616_3@
另一个用例是在自动化测试中嘲笑:有时您想要创建一个像某个类(通常是一个模型实例)的对象,但是由于技术原因而不是该类的实例.@H_616_3@
以下是如何创建将所有方法委托给内部存储的fixnum的特定整数类型:@H_616_3@
require 'delegate' require 'forWARDable' # Integer represenTing a page number class Pagenumber < DelegateClass(Integer) extend ForWARDable def initialize(value,Name) @name = name super(value) end def inspect "#{@namE} #{to_i}" end alias_method :to_i,:__getobj__ def_delegators :to_i,:instance_of?,:kind_of?,:is_a? end
page = Pagenumber.new(1,"page") page.is_a? Fixnum #=> true
但是没有办法可以让它通过@L_489_0@型检查:@H_616_3@
# my problem: Fixnum === page #=> false
事实上,我的对象没有这个检查是非常不幸的,因为===方法在内部使用case语句:@H_616_3@
case page when Fixnum # it will never get here when String # ... else # ... end
模块#===方法实际上是rb_obj_is_kind_of
的rb_obj_is_kind_of
C API方法.后者的实现很短,我将其粘贴到这里:@H_616_3@
VALUE rb_obj_is_kind_of(VALUE obj,VALUE C) { VALUE cl = CLASS_OF(obj); /* Type checking of `c' omitted */ while (cl) { if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(C)) return Qtrue; cl = RCLASS_SUPER(cl); } return Qfalse; }
可以看到,这种方法遍历被检查对象的祖先,并以两种方式进行比较:首先,它检查祖先是否与传递的模块相同,然后检查它们是否具有相同的方法表.@H_616_3@
后一个检查是必需的,因为Ruby中包含的模块似乎被插入到继承链中,但是由于一个模块可能被包含在其他几个模块中,所以它不是插入到链中的真实模块,而是代理对象,常数和方法表指向原始模块.@H_616_3@
ruby-1.9.2-p136 :001 > Object.ancestors => [Object,Kernel,BasicObject] ruby-1.9.2-p136 :002 > Object.ancestors.map { |mod| Object.new.is_a? mod } => [true,true,true]
在这里,Object和BasicObject将被第一次检查成功比较,而Kernel由第二个检查成功比较.@H_616_3@
即使您尝试使用(扩展名为C)的代理对象来尝试欺骗rb_obj_is_kind_of方法,它将需要具有与实际Fixnum相同的方法表,这将有效地包括所有Fixnum的方法.@H_616_3@
以上是大佬教程为你收集整理的模仿另一个Ruby类,所以对象通过===类型检查全部内容,希望文章能够帮你解决模仿另一个Ruby类,所以对象通过===类型检查所遇到的程序开发问题。
如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。
本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。