[英]implementing the comparison operators - Ruby
我是Ruby
新手,我正在尝试实现Grades
之间的比较,如示例所示
include Comparable
class Grade
attr_accessor :grades, :grade
def initialize( grade = "" )
self.grades = { :nil => -1, :"F" => 0, :"D-" => 1, :"D" => 2, :"D+" => 3,
:"C-" => 4, :"C" => 5, :"C+" => 6, :"B-" => 7, :"B" => 8,
:"B+" => 9, :"A-" => 10, "A+" => 11 }
if self.grades[ grade ]
self.grade = grade
else
self.grade = nil
end
end
def <=>( other )
if self.grades[ self.grade ] < self.grades[ other.grade ]
return -1
elsif self.grades[ self.grade ] == self.grades[ other.grade ]
return 0
else
return 1
end
end
end
a_plus = Grade.new("A+")
a = Grade.new("A")
[a_plus, a].sort # should return [a, a_plus]
所以,我得到了:
grade.rb:31:in `<': comparison of Fixnum with nil failed (ArgumentError)
from grade.rb:31:in `<=>'
from grade.rb:43:in `sort'
from grade.rb:43:in `<main>'
我只想在Ruby中实现对象之间的Comparison
来自Ruby Doc模块可比较 :
可比较使用<=>来实现传统的比较运算符(<,<=,==,> =和>)和?之间的方法。
当你想实现这样的事情时,只实现<=>
。 其余的应该自动跟随。 例如,如果你定义<
,那么你将搞乱这个课程。
你可以这样做:
class Grade
include Comparable
attr_reader :index
@@grades = %w[F D- D D+ C- C C+ B- B B+ A- A+]
def initialize (grade = nil); @index = @@grades.index(grade).to_i end
def <=> (other); @index <=> other.index end
end
a_plus = Grade.new("A+")
a = Grade.new("A")
a_plus > a
# => true
[a_plus, a].sort
# => `[a, a_plus]` will be given in this order
你只需要如下:
class Foo
include Comparable
attr_reader :bar
def initialize bar
@bar = bar
end
def <=>(another_foo)
self.bar <=> another_foo.bar
end
end
因此,在<=>
的定义中,您可以添加自己的逻辑。
评论您的原始帖子:当您收到消息时
in'>':nil的未定义方法'>':NilClass(NoMethodError)
只需输入print语句即可显示值。 因此你会立即发现在initialize
, self.grades[ self.grade ]
返回nil,因为Grade.new("A+")
的参数是一个String,但是hash中的键是符号,所以你需要转换为to_sym
。
您的原始类重新排列,带有print语句(并且只显示>(other)):
class Grade
attr_reader :grade
@@grades = { :nil => -1, :"F" => 0, :"D-" => 1, :"D" => 2, :"D+" => 3,
:"C-" => 4, :"C" => 5, :"C+" => 6, :"B-" => 7, :"B" => 8,
:"B+" => 9, :"A-" => 10, :"A+" => 11 }
def initialize( p_grade = "" )
@grade = p_grade if @@grades[ p_grade.to_sym ]
puts "init param=#{p_grade} value=<#{@@grades[ p_grade.to_sym ]}> @grades=<#{@grade}>"
end
def >( other )
puts "in >( other ) : key1=#{self.grade} key2=#{other.grade}"
puts "in >( other ) : $#{@@grades[ self.grade ]}$ ??? $#{@@grades[ other.grade ]}$"
return @@grades[ self.grade ] > @@grades[ other.grade ]
end
end
print '--- Grade.new("A+") : '; a_plus = Grade.new("A+")
print '--- Grade.new("A") : '; a = Grade.new("A")
print '--- a_plus > a : '; p a_plus > a
执行:
$ ruby -w t.rb
--- Grade.new("A+") : init param=A+ value=<11> @grades=<A+>
--- Grade.new("A") : t.rb:9: warning: instance variable @grade not initialized
init param=A value=<> @grades=<>
--- a_plus > a : in >( other ) : key1=A+ key2=
in >( other ) : $$ ??? $$
t.rb:15:in `>': undefined method `>' for nil:NilClass (NoMethodError)
from t.rb:21:in `<main>'
Grade.new("A")
:由于散列中不存在A ,因此未设置实例变量@grade,并且self.grades[ self.grade ] > ...
将消息>
发送到nil,一个实例NilClass没有定义>
。
注意诀窍@grades = <#{xyz}>,用<>或$$围绕内插值使得当值为nil时显示更明显。
还要注意ruby -w t.rb中的-w,显示有趣的警告消息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.