2

有没有办法定义一个可以强制为 String 或 Fixnum 或 Float 的对象?这用于收集值并使用它们评估一组受限的简单表达式的系统。

我试过了:

class EmptyValue < Numeric
  def to_s; ''; end
  def to_str; ''; end
  def to_i; 0; end
  def to_int; 0; end
  def to_f; 0.0; end
end

但这失败了

1 + e
TypeError: EmptyValue can't be coerced into Fixnum
4

2 回答 2

1

再戳一下,这适用于我所有的用例:

class EmptyValue < Numeric
  def to_s; ''; end
  def to_str; ''; end
  def to_i; 0; end
  def to_int; 0; end
  def to_f; 0.0; end

  def +(other)
   case other
   when String
     to_s + other
   when Fixnum
     to_i + other
   when Float
     to_f + other
   end
  end
end
于 2013-06-11T22:34:53.783 回答
0

这是我很久以前所做的:

class NullObject
  attr_reader :null_object_type, :recorded_messages
  alias ρ recorded_messages
  def initialize( type_of_null_object = nil )
    @null_object_type = type_of_null_object
    @recorded_messages = []
  end
  def null_object? null_type = nil
    null_object_type == null_type
  end
  alias null? null_object?
  def to_a; [] end
  def to_s; "null #{null_object_type}".strip end
  def to_f; 0.0 end
  def to_i; 0 end
  def present?; false end
  def empty?; true end
  def blank?; true end
  def inspect
    "NullObject #{null_object_type}".strip
  end
  def method_missing ß, *aj, &b      # :nodoc:
    @recorded_messages << [ ß, aj, b ]; self
  end
  def respond_to? ß, *aj, &b         # :nodoc:
    true
  end

  protected
  def == other                       # :nodoc:
    null_object_type == other.null_object_type
  end
end # class NullObject

# Strong zero.
# 
ZERO = NullObject.new
ZERO.instance_exec {
  ɪ = self
  singleton_class.class_exec do
    define_method :zero do ɪ end
  end

  def * other; other.class.zero end
  def / other
    self unless other.zero?
    raise ZeroDivisionError, "The divisor is zero! (#{other})"
  end
  def + other; other end
  def - other; -other end
  def coerce other
    return other, other.class.zero
  end
  def zero?; true end
  def to_s; "∅" end
  def inspect; to_s end
  def to_f; 0.0 end
  def to_i; 0 end
  def == other
    z = begin
          other.class.zero
        rescue NoMethodError
          return false
        end
    other == z
  end
}

class << Numeric; def zero; 0.0 end end
class << Integer; def zero; 0 end end
class << Float; def zero; 0.0 end end
class << Rational; def zero; Rational 0, 1 end end
class << Complex; def zero; Complex 0, 0 end end
class << String; def zero; '' end end
class << Array; def zero; [] end end
class << Hash; def zero; {} end end

所以,现在你有0 + ZERO #=> 0. 我称之为“强零”。但这是一个黑客。我有一种直觉,这不是一个很好的做法。

于 2013-06-12T03:11:51.520 回答