有没有办法定义一个可以强制为字符串、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

最佳答案

这是我很久以前做的:

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。我称之为“强零”但这是一个黑客。我有一种直觉,认为这不是一个好的做法。

07-25 21:50