如何创建一个在 Ruby 中充当 False 的对象 [英] How to create an Object who act as a False in Ruby

查看:30
本文介绍了如何创建一个在 Ruby 中充当 False 的对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想这样做

lol = Klass.new(values)

unless lol 
   print "false"
end

lol.other_method  # it is not nil or false, it is a Klass instance!

但是,在这种情况下,lol 不是 nil 或 false,而是可以根据某些内部值充当 false 的对象.我有这个选择

But lol, in this case, is not nil or false, but an object who can act as a false based on some internal value. I have this alternative

lol = Klass.new(values)

unless lol.to_bool
   print "false"
end

但恕我直言,这很丑陋.

But it is ugly IMHO.

我正在考虑扩展 FalseClass 或使用 == 但没有成功.有什么想法吗?

I was thinking in extend the FalseClass or play with == but without success. Any Ideas?

推荐答案

很遗憾,这是不可能的.

Unfortunately, this is not possible.

这是 Ruby 不面向对象的烦人情况之一.在面向对象中,一个对象必须可以模拟另一个对象(实际上,这取决于你问的是谁,这就是面向对象的定义——记住 OO 出现了模拟),但不可能构建一个模拟 false 的对象.

This is one of those annoying cases where Ruby is not object-oriented. In OO, it must be possible for one object to simulate another (in fact, depending on whom you ask, this is the very definition of OO – remember that OO came out of simulation), but it is not possible to build an object which simulates false.

这是因为,在 Ruby 中,条件控制结构被嵌入语言中并且不会转换为消息发送,而在其他 OO 语言中,它们只是常规的消息发送(或至少转换为消息发送,就像 for 转换为 each).例如,在 Smalltalk 中,布尔值实际上是使用您从 Lambda Calculus 中知道的布尔值的 Church 编码实现的,然后转换为 Ruby 它们看起来有点像这样:

This is because, in Ruby, conditional control structures are baked into the language and don't translate into message sends, whereas in other OO languages they are just regular message sends (or at least translate into message sends, just like for in Ruby translates into each). For example, in Smalltalk, Booleans are actually implemented using the Church encoding of Booleans you know from Lambda Calculus, and translated to Ruby they look a bit like this:

class FalseClass
  def if(&block)
    # do nothing
  end

  def if_then_else(then_lambda, else_lambda)
    else_lambda.()
  end

  def not
    true
  end

  def and(&block)
    self
  end

  def or(&block)
    block.()
  end
end

TrueClass 只是镜像:

class TrueClass
  def if(&block)
    block.()
  end

  def if_then_else(then_lambda, else_lambda)
    then_lambda.()
  end

  def not
    false
  end

  def and(&block)
    block.()
  end

  def or(&block)
    self
  end
end

然后,而不是像

if 2 < 3 then foo end
if 2 < 3 then bar else baz end

你会

(2 < 3).if { foo }
(2 < 3).if_then_else(-> { bar }, -> { baz })

# using the new keyword arguments in Ruby 2.0, it almost reads like Smalltalk:
class FalseClass
  def if(then: -> {}, else: -> {})
    else.()
  end
end

class TrueClass
  def if(then: -> {}, else: -> {})
    then.()
  end
end

(2 < 3).if(then: -> { bar }, else: { baz })

这样,您只需实现相应的方法即可轻松创建一个模拟 false 的对象.

That way, you can easily create an object which simulates false simply by implementing the respective methods.

在其他情况下,某些对象确实绝对必须是特定类的实例,而不仅仅是说出正确的协议,Ruby 提供了一个逃生舱口.例如,如果一个方法真的需要一个 Array 作为参数,那么它会首先尝试调用 to_ary 至少给你一个机会将您的对象转换为 Array.to_strto_intto_procto_float 等也是如此.但是没有等效的 to_bool 协议.

In other cases, where some object really absolutely must be an instance of a specific class and not just speak the correct protocol, Ruby provides an escape hatch. For example, if a method really requires an Array as an argument, then it will first try to call to_ary to at least give you a chance to convert your object into an Array. The same goes for to_str, to_int, to_proc, to_float etc. But there is no equivalent to_bool protocol.

这篇关于如何创建一个在 Ruby 中充当 False 的对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆