gpt4 book ai didi

Ruby 为不同类型的对象设置成员资格

转载 作者:数据小太阳 更新时间:2023-10-29 07:58:39 30 4
gpt4 key购买 nike

Ruby 不是一种类型化语言,因此我觉得这很奇怪。示例:

class Test
attr_reader :field

def initialize(f)
@field = String(f)
end

def ==(other)
field == String(other)
end

def eql?(other)
field.eql? String(other)
end

def hash
field.hash
end

def to_s
field
end
end

s = Set.new([Test.new('string')])
# => [#<Test:0x007fc97da17ea0 @field="string">]

puts Test.new('string').eql?(Test.new('string'))
# true

puts Test.new('string').hash == Test.new('string').hash
# true

puts s.member? Test.new('string')
# true

puts s.member? Test.new('other')
# false

puts Test.new('string') == 'string'
# true

puts Test.new('string').eql? 'string'
# true

puts Test.new('string').hash == 'string'.hash
# true

但是,

puts s.member? 'string'
# false

Ruby 似乎在内部强制执行一些类型检查。应该是这样吗?

最佳答案

您的主要问题是 String#eql? :

puts Test.new('string').eql? 'string'
# true
puts 'string'.eql? Test.new('string')
# false

你是对的,似乎有一些内部类型检查:

rb_str_eql(VALUE str1, VALUE str2)
{
if (str1 == str2) return Qtrue;
if (!RB_TYPE_P(str2, T_STRING)) return Qfalse;
return str_eql(str1, str2);
}

请注意,您的示例在以其他方式使用时有效:

s = Set.new(['string'])
puts s.member? Test.new('string')
# true

如果你真的想实现这种行为,你可以猴子补丁String#eql?:

module TestStringEquality
def eql?(other)
other.is_a?(Test) ? other.eql?(self) : super
end
end

s = Set.new([Test.new('string')])
puts s.member? 'string'
# false

class String
prepend TestStringEquality
end

puts s.member? 'string'
# true

小心,这种方法可能在每个 gem 中都使用。

最后,请记住Set是带有 Hash 的纯 Ruby 实现作为后端。它可能会使通过谷歌搜索信息和文档变得更容易。

关于Ruby 为不同类型的对象设置成员资格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43232685/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com