Божидар обнови решението на 26.10.2014 12:54 (преди около 10 години)
+class NumberSet
+ include Enumerable
+
+ attr_accessor :container
+
+ def initialize(initial_container = [])
+ @container = initial_container
+ end
+
+ def <<(number)
+ unless @container.include? number
+ @container << number
+ end
+ end
+
+ def size
+ @container.size
+ end
+
+ def empty?
+ @container.empty?
+ end
+
+ def each(&proc)
+ @container.each { |e| yield(e) }
+ end
+
+ def [](filter)
+ NumberSet.new(@container.select(&filter.filter_proc))
+ end
+
+end
+
+class Filter
+
+ attr_accessor :filter_proc
+
+ def initialize(&proc)
+ @filter_proc = proc
+ end
+
+ def &(other)
+ Filter.new do |number|
+ @filter_proc.call(number) && other.filter_proc.call(number)
+ end
+ end
+
+ def |(other)
+ Filter.new do |number|
+ @filter_proc.call(number) || other.filter_proc.call(number)
+ end
+ end
+
+end
+
+class SignFilter < Filter
+
+ def initialize(sign)
+ @filter_proc = case sign
+ when :positive then Proc.new { |number| number > 0 }
+ when :non_positev then Proc.new { |number| number <= 0 }
+ when :negative then Proc.new { |number| number < 0 }
+ when :non_negative then Proc.new { |number| number >= 0 }
+ end
+ end
+
+end
+
+class TypeFilter < Filter
+
+ def initialize(type)
+ @filter_proc = case type
+ when :real
+ Proc.new { |number| number.is_a? Float or number.is_a? Rational }
+ when :complex
+ Proc.new { |number| number.is_a? Complex }
+ when :integer
+ Proc.new { |number| number.is_a? Integer }
+ end
+ end
+
+end
Здрасти,
Ето няколко неща за размисъл:
- Не оставяй празен ред преди първия и след последния метод в клас.
-
attr_accessor
-ите не са ти необходими. -
NumberSet#each
трябва да работи подобно наArray#each
, когато не му подадеш блок. - Вместо да даваш стойност на
@filter_proc
вSignFilter
,TypeFilter
можеш да подадеш блок на конструктора наFilter
използвайкиsuper() { |number| ... }
. - Скрий
@filter_proc.call(number)
зад метод. Не е добре да показваш ламбдата на въшния свят. По-добре да имаш стабилен интерфейс.