Ruby – 在Ruby中扩展内置变量

我想在Ruby中扩展变量的function。 原因是我正在研究类似系统或值检查器的东西(这听起来有点疯狂,但整个想法是长期解释,只是我想扩展默认变量的原因)。

我已经读到在Ruby中,一切都是对象; 所以变量就是对象。 对于可以通过元编程改变的东西,Ruby应该是相当自由的。

是否有某种与我可以扩展的局部变量相关联的“类”?

我想为每个包含类型的字符串表示forms的变量关联一个字符串变量。 此外,我想拦截变量赋值,并在每次为变量赋值新值时执行方法。 这是我可以检查,如果新值根据类型是正确的(存储为变量中的字符串)。

如果Ruby中的局部变量被定义为类的对象,我可以扩展该类或通过ruby mixin修改它。

解决方法是为我的变量创建一个新类(而不是使用Ruby的局部变量中的构建)。 该类可以具有值属性,类型的属性(存储为字符串)以及get和set方法。 这样我可以解决我的问题,但我想在ruby中扩展内置变量,如果可能的话。

目前的工作正在进行中

class Fixnum attr_accessor :tp @tp def mytype ( type ) @tp = type end def typecheck #call typechecker puts "checked" end end 

测试代码:

 a = 3 a.mytype("nat") puts a.tp a.typecheck 

还有两个问题。 首先 ,我认为不可能向Fixnum添加新的构造函数。 其次 ,我想拦截变量访问,即“b = a”调用a的方法’typecheck’。 但这需要类似于面向方面编程的东西,我不确定这是否可以通过Ruby的元编程方便解决。

我已经读过,在Ruby中,一切都是对象

这取决于你对“ 对象 ”和每个“ 事物 ”的定义。 “ 对象 ”可以表示“ 可以由程序操纵的实体 ”(我将从现在开始称之为对象 ),或“ 作为对象系统成员的值 ”(我将从现在开始称之为Object )。

在Ruby中,程序可以操作的所有东西(即每个对象 )也是一个Object ,即一个类的实例。 例如,这与Java不同,其中基元可以由程序操纵(即,在该意义上的对象 ),但不是Objects 。 在Ruby中,这种区别不存在:每个对象都是一个Object ,每个Object也是一个对象

但是,语言中有些东西 不能被程序操纵,也不是类的实例,即它们既不是对象也不是Object 。 例如,这些是方法,变量,语法,参数列表,参数列表,关键字。

注意:您可以使用Ruby的reflectionAPI为您提供表示方法或参数列表的对象,但该对象只是一个代理,它不是真实的。

所以,当我们说“ 一切都是一个对象 ”时,我们真正的意思是“每个对象都是一个Object ”,即程序可以操作的所有东西也是对象系统的一个成员,换句话说,在对象系统之外没有值(与Java中的原语不同)。 我们并不是说该语言中存在的所有内容也可以在程序运行时进行操作。

所以变量就是对象

不,不幸的是,它们既不是对象也不是Object

这也在Ruby语言规范中明确说明(我强调):

6.2变量

6.2.1一般说明

变量由名称表示,并引用一个对象,称为变量的值。 变量本身不是对象

在Matz和David Flanagan撰写的The Ruby Programming Language一书中它在第2页说:

每个值都是一个对象

注意,它并不是说每件事 ,只说每一个

另请参阅问题变量是ruby中的对象吗?

你可以做几件事。 对于初学者来说,所有(或几乎所有)Ruby类(包括诸如数字的“基元”)都支持to_s方法,该方法返回对象的字符串表示。 对于数字,to_s将仅返回该数字的字符串表示(例如,42表示“42”)。 为其他类返回的字符串值会有所不同。 好处是你可以通过“猴子修补”来覆盖类的方法 。 这是一个非常人为的例子:

 class Array def to_s return "An array of size #{self.size}." end end a = [1, 2, 3, 4] puts a.to_s # => "An array of size 4." 

对于关于每次设置变量值时执行方法的其他问题,处理此问题的方法是始终通过其访问器方法与变量进行交互。 这样,您可以在属性的getter和setter方法中实现自定义代码(或者只是从访问器内部调用另一个方法)。 像这样:

 class MyClass # Use the default getter for var. attr_reader :var def initialize @var = 1 end # Custom setter for var. def var= v @var = v puts "var changed to #{v}" end end mc = MyClass.new mc.var = 9 # => "var chaged to 9" 

你可以这样做,但它只适用于全局:

 $type_checked = {:$a => String, :$b => Array} $type_checked.keys.each do |var| trace_var(var) do |obj| puts "hey, don't assign #{var} to a #{obj.class}" unless $type_checked[var] == obj.class #or raise an Error end end $a = 1 $a = "a" $b = 1 #output: #hey, don't assign $a to a Fixnum #hey, don't assign $b to a Fixnum 

但这显然违背了语言的范畴。