可以强制转换为String,Fixnum还是Float的对象?

时间:2013-06-11 22:19:34

标签: ruby

有没有办法定义一个可以强制转换为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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分: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。我称之为“强零”。但这是一个黑客。我有一种直觉,这不是一个好习惯。