我设计了一个NumberSet类,它包含一个数组,我必须在其上实现某些过滤器,我将其设计为类。代码是:
class NumberSet
include Enumerable
def initialize
@arr=[]
end
def each (&block)
@arr.each do |member|
block.call (member)
end
end
def << number
@arr<<number unless @arr.include?(number)
end
def [] (sito)
@arr.select{|number| sito.filter(number)}
end
end
class Filter
attr_reader :filter
def initialize &block
@filter = block
end
def filter number
@filter.call(number)
end
end
class SignFilter
def initialize(sign)
@sign = sign
end
def filter number
return true if(@sign==:negative && number<0)
return true if(@sign==:positive && number>0)
return true if(@sign==:nonnegative && number >= 0)
return true if(@sign==:nonpositive && number <= 0)
end
end
class TypeFilter
def initialize(sign)
@sign = sign
end
def filter number
return true if (@sign==:complex && number.is_a?(Complex) == true)
return true if (@sign==:integer && number.is_a?(Integer) == true)
return true if (@sign==:real && (number.is_a?(Rational) == true
|| number.is_a?Float) == true))
end
end
一切运作良好,但我还必须定义&
和|
运算符,使它们像交集和并集一样工作,这意味着&
应该只获得满足所有过滤器和满足至少一个过滤器的|
个数字。
另外,语法
numbers[SignFilter.new(:non_negative) & Filter.new { |number| number.even? }]
必须有效。
如何定义它们才能正常工作?
要回答一些评论,我正在寻找一种让操作符&
,|
以我想要的方式工作的方法。问题不在于如何编写语法,而是def
和end
之间的代码应该是什么。
答案 0 :(得分:0)
您可以像任何其他方法一样定义它们。我只是试着这个例子:
class Adder
def &(number_to_add)
number_to_add + 20
end
end
a = Adder.new
a & 20
#=> 40
答案 1 :(得分:0)
就像一张纸条,因为这看起来像是气味:
def filter number
return true if(@sign==:negative && number<0)
return true if(@sign==:positive && number>0)
return true if(@sign==:nonnegative && number >= 0)
return true if(@sign==:nonpositive && number <= 0)
end
为什么试试这个:
class SignFilter
@@signs = {negative: "<", positive: ">", nonnegative: ">=", nonpositive: "<="}
@@signs.each do |meth,sign|
define_method meth do |number|
number.send(sign,0)
end
end
def initialize(sign)
@sign = sign
end
def filter(number)
self.public_send(@sign,number)
end
end
您可以对TypeFilter执行相同操作(提示Numeric
具有#real?
方法)或单独定义方法。我知道这不是你的实际问题的答案,我只是喜欢干净的代码。 :)
答案 2 :(得分:0)
这是值得冥想的事情......
def filter number
return true if(@sign==:negative && number<0)
return true if(@sign==:positive && number>0)
return true if(@sign==:nonnegative && number >= 0)
return true if(@sign==:nonpositive && number <= 0)
end
可以写成:
def filter number
( @sign == :negative && number < 0 ) ||
( @sign == :positive && number > 0 ) ||
( @sign == :nonnegative && number >= 0 ) ||
( @sign == :nonpositive && number <= 0 )
end
为什么呢?因为每个测试都返回true或false。如果一个返回true,则||
加入的其他任何一个都将被测试,因为||
短路,并且Ruby看到的最终值将为true,将返回。如果第一个失败,||
将告诉Ruby检查下一个,并在链上。
这模仿了原始代码的行为,但两者都存在问题。在成功的结果中,返回true。失败将是零。这是你想要的,或者你想要返回false,使方法只返回true / false?在Ruby中,nil是一个“假”值,因此它的工作方式相同,但为了保持一致性,您可能只想返回true / false。
此外,作为编码式推荐,请在运算符之间使用空格。
@sign==:negative && number<0
不像
那样可读@sign == :negative && number < 0
在调试时或将代码传递给其他人进行维护之后,可读性非常重要。人们喜欢说他们稍后会修复它,但后来,代码保持不变并被投入生产,等待在凌晨3点激怒一些可怜的灵魂。
答案 3 :(得分:0)
这样的事情怎么样?
class Filter
def initialize(&filter_block)
@filter_block = filter_block
end
def filter(number)
@filter_block.call(number)
end
def &(other)
CompositeFilterAND.new(self, other)
end
def |(other)
CompositeFilterOR.new(self, other)
end
end
class CompositeFilterAND
attr_accessor :left, :right
def initialize(left, right)
@left, @right = left, right
end
def filter(number)
@left.filter(number) && @right.filter(number) # This is the magic.
end
end
class CompositeFilterOR
attr_accessor :left, :right
def initialize(left, right)
@left, @right = left, right
end
def filter(number)
@left.filter(number) || @right.filter(number) # And this.
end
end