在Ruby中重新定义平等实际上是如何工作的?
作为一名新手,我仔细阅读了大量关于如何重新定义平等的指南,但没有一本真正解释它是如何工作的,只是解释了写什么 这样的代码在Ruby中重新定义平等实际上是如何工作的?,ruby,equality,Ruby,Equality,作为一名新手,我仔细阅读了大量关于如何重新定义平等的指南,但没有一本真正解释它是如何工作的,只是解释了写什么 这样的代码 class Person attr_reader :name def initialize(name) @name = name end def ==(whatever) self.name == whatever.name end end 将考虑 name1 = Person.new("Jack") name1 = Person.n
class Person
attr_reader :name
def initialize(name)
@name = name
end
def ==(whatever)
self.name == whatever.name
end
end
将考虑
name1 = Person.new("Jack")
name1 = Person.new("Jack")
及
相等,而旧的==
方法则没有,因为它比较了其他方法
然而,它实际上是如何工作的?什么是“随便”(许多人似乎写“其他”)以及它做什么?编辑:为了澄清,我理解这样做的意义,我只是不理解内部工作原理。一步一步发生了什么?whatever.name做什么?为什么?在==方法中返回真/假值如何帮助重新定义它?这些就是我在这里要问的问题
什么是“无论如何”
当你打电话时:
name1 == name2
Ruby在内部将其“转换”为函数调用:
name1.==(name2)
=
在这个函数调用中没有“特殊”的含义,它只是
函数名(就像foo
或do\u something
可能是函数名一样)
如您所见,无论什么
都是传递给函数的参数,函数位于=
的右侧
这称为“运算符重载”;这意味着操作员可以根据变量做不同的事情;您可以对所有运算符执行此操作,例如
(大于)、=
(赋值)等
为什么需要self.name而不仅仅是name或@name
都是有效的,;在本例中,name
、self.name
和@name
引用相同的变量。有些人只是喜欢写self.name,我就是其中之一,更明确的是,你指的是实例变量,而不是函数中的局部变量(不太“神奇”)。我也有很长的Python背景,在那里,self
是必须的,所以我已经习惯了。不过,在Ruby中,只写
name
似乎更为常见
而旧的==方法没有,因为它比较了其他方法
来自(我的):
在对象级别,==仅当obj和其他
是同一个对象。通常,此方法在中被重写
子类提供特定于类的含义
因此,在您的例子中,name1
和name2
显然不是同一个对象,即使它们具有相同的值。露比不知道你认为什么是“代码>人<代码>的值,所以当你认为两个对象是相同的时,你需要改写<代码>=运算符来告诉Ruby。< P>使用你自己的例子:
Person.new("Jack") == Person.new("Jack")
这里比较的是对象作为一个整体,它将具有不同的object\u id
s。这将导致相等比较失败
通过覆盖
==
,您将使比较查看对您实际重要的内容,在本例中是名称
属性。因此,在第二个Person
对象中传递什么来计算相等性,实际上它是在查看name
属性,而不是像覆盖=
之前那样查看整个对象。要回答您的问题,您可以在比较中使用name
或@name
,这无关紧要self
只是指等式左侧的对象,无论什么
都是右侧的对象。OP的标题询问“在Ruby中重新定义平等实际上是如何工作的?”。一般的答案是:
Ruby有几个方法可以被认为是“平等的”:==
,#equal?
,#eql?
,==
,所有这些方法的具体任务都与其他方法略有不同。在幕后,诸如#==
等操作符方法的工作原理如下:
42 == 42
被翻译成
42.==( 42 )
也就是说,消息:==,42
被发送到号码42
:
42.send( :==, 42 )
在任何对象上重新定义#==
方法时,此重新定义的方法将处理消息
虽然其他答案提到了对象#=
的作用,但您可以注意到,对于可比较的对象(即可以添加mixincompariable
的对象),您应该重新定义方法#
,mixin将自行处理#=
(以及
和code>以及一系列其他方法)
此外,OP还提出了一些次要的语法问题:什么是什么,以及是否需要self.name
。这些都与等式方法无关
self.name
不是必需的,因为self
始终是隐式接收者。可以只编写name==which.name
,而不是self.name==which.name
。过度使用显式的self
可以被认为是一种pythonism@name
不能使用,因为它表示其他内容(引用实例变量)
在方法定义中
def ==( whatever )
name == whatever.name
end
无论什么
都是一个参数。正在使用单个参数定义该方法。因此,当调用该方法时,它将需要一个参数,并将该参数指定给局部变量which
。这只是方法定义语法,没有其他内容
总而言之,OP询问的#=
版本将Person
类的对象按名称进行比较,如果它们的名称相等,即使它们不是相同的对象,也会认为它们相等。请参见下面我的答案:
然而,它实际上是如何工作的
编写name1==name2时,实际上是将name2变量发送到实例方法
==(无论什么)
什么是“随便”(许多人似乎写“其他”)以及它做什么
是na吗
name1 = Person.new("Jack")
name2 = Person.new("Jack")
name1 == name2
name1.==(name2)
def foo(bar)
puts bar
end
a = 'b'
foo(a) #=> "b"