等式运算符的顺序在Ruby中重要吗?

等式运算符的顺序在Ruby中重要吗?,ruby,operators,bcrypt,equality,commutativity,Ruby,Operators,Bcrypt,Equality,Commutativity,我在Ruby程序中使用了bcrypt库。我注意到相等运算符的顺序似乎很重要。根据哪个变量在“==”的左边或右边,我会得到不同的结果。 以下是一个示例程序: require 'bcrypt' my_pw = "pw1" puts "This is my unhashed password: #{my_pw}" hashed_pw = BCrypt::Password.create(my_pw) puts "This is my hashed pas

我在Ruby程序中使用了bcrypt库。我注意到相等运算符的顺序似乎很重要。根据哪个变量在“==”的左边或右边,我会得到不同的结果。 以下是一个示例程序:

require 'bcrypt'
my_pw = "pw1"
puts "This is my unhashed password: #{my_pw}"
hashed_pw = BCrypt::Password.create(my_pw)
puts "This is my hashed password: #{hashed_pw}"

20.times{print"-"}
puts

puts "my_pw == hashed_pw equals:"
if (my_pw == hashed_pw)
  puts "TRUE"
else
  puts "FALSE"
end

puts "hashed_pw == my_pw equals:"
if (hashed_pw == my_pw)
  puts "TRUE"
else
  puts "FALSE"
end
问候
schande

例如,如果两个操作数都是字符串类型,则表达式将是等效的。在本例中,一个操作数是
字符串
,另一个是
BCrypt::Password
。因此,
my_pw==hashed_pw
调用String类中定义的相等方法,而
hashed_pw==my_pw
调用BCrypt::Password中定义的相等方法


我从未使用过BCrypt::Password,但希望前者得到
false
,后者得到
true

如果两个操作数都是字符串类型,则表达式将是等效的。在本例中,一个操作数是
字符串
,另一个是
BCrypt::Password
。因此,
my_pw==hashed_pw
调用String类中定义的相等方法,而
hashed_pw==my_pw
调用BCrypt::Password中定义的相等方法


我从未使用过BCrypt::Password,但我希望前者得到
false
,后者得到
true

在Ruby中,您可以覆盖给定类或实例的相等方法:

class Test
  define_method(:==) do |_other|
    true
  end
end

Test.new == 'foo' # => true
Test.new == nil # => true
Test.new == 42 # => true

'foo' == Test.new # => false
nil == Test.new # => false
42 == Test.new # => true

一般来说,重写相等而不使其对称被认为是不好的做法,但您有时会在野外看到它。

在Ruby中,您可以重写给定类或实例的相等方法:

class Test
  define_method(:==) do |_other|
    true
  end
end

Test.new == 'foo' # => true
Test.new == nil # => true
Test.new == 42 # => true

'foo' == Test.new # => false
nil == Test.new # => false
42 == Test.new # => true

一般来说,忽略等式而不使其对称被认为是不好的做法,但你有时会在野外看到它。

是的,这是有区别的

my_pw==hashed_pw
调用
my_pw
字符串上的
=
方法,并将
hashed_pw
作为参数传递。这意味着您正在使用
String#=
方法。从:

如果
对象
具有相同的长度和内容,则返回
true
;作为
self
<代码>错误否则

hashed_pw==my_pw
BCrypt::Password
的实例上调用
=
方法,并将
my_pw
作为参数传递。从以下文件:

将潜在机密与哈希进行比较。如果机密是原始机密,则返回
true
,否则返回
false


是的,有区别

my_pw==hashed_pw
调用
my_pw
字符串上的
=
方法,并将
hashed_pw
作为参数传递。这意味着您正在使用
String#=
方法。从:

如果
对象
具有相同的长度和内容,则返回
true
;作为
self
<代码>错误否则

hashed_pw==my_pw
BCrypt::Password
的实例上调用
=
方法,并将
my_pw
作为参数传递。从以下文件:

将潜在机密与哈希进行比较。如果机密是原始机密,则返回
true
,否则返回
false


这与平等没有任何关系。这只是面向对象编程的基础

在OOP中,所有计算都是由对象向其他对象发送消息来完成的。OOP的一个基本属性是接收方对象,并且只有接收方对象决定如何响应此消息。这就是在OOP中实现封装、数据隐藏和抽象的方式

因此,如果将消息
m
发送到对象
a
并将
b
作为参数传递,则
a
将决定如何解释此消息。如果将消息
m
发送到对象
b
并将
a
作为参数传递,则由
b
决定如何解释此消息。没有任何内置机制可以保证
a
b
对该消息的解释相同。只有当这两个对象决定相互协调时,响应才会真正相同

如果你想一想,如果
2-3
3-2
有相同的结果,那将是非常奇怪的

这正是此处发生的情况:在第一个示例中,您将消息
==
发送到
my_pw
,并将
哈希_pw
作为参数传递
my_pw
是的一个实例,因此
=
消息将被发送到该方法。此方法知道如何将接收器对象与另一个
字符串
进行比较。然而,它不知道如何将接收器与a进行比较,这就是hashed_pw的类

如果你仔细想想,这是有道理的:
BCrypt::Password
是Ruby之外的第三方类,一个内置Ruby类怎么知道在实现
String
类时根本不存在的东西呢

另一方面,在第二个示例中,您将消息
==
发送到
散列\u pw
,并将
my\u pw
作为参数传递。此消息被发送到方法,该方法不知道如何将接收方与
字符串进行比较:

方法:
BCrypt::Password#==
中定义:lib/bcrypt/password.rb

#==(秘密)
⇒ <代码>对象

也称为:
是密码吗?

将潜在机密与哈希进行比较。如果机密是原始机密,则返回
true
,否则返回
false

事实上,这个特殊情况下的问题甚至比最初出现的问题更微妙

我在上面写道,
String#=
不允许
#==(secret) ⇒ Object