为什么Ruby有TrueClass和FalseClass而不是一个布尔类?

kik*_*ito 73 ruby language-design

当我发现这个值时,我正在努力序列化值.Ruby有一个TrueClass类和一个FalseClass类,但它没有Boolean类.我想知道为什么会这样.

我看到使用a的一些优点Boolean; 例如,字符串解析可以集中在它上面.

Ruby开发人员比我聪明,所以必须有很多我没看到的好理由.但是现在看起来我喜欢OneClass和一个TwoClass而不是Fixnum.

Jör*_*tag 60

类的目的是将类似对象或具有相似行为的对象组合在一起.1并且2非常相似,因此它们在同一个班级中是完全合理的.truefalse不过是相似的.事实上,他们的全部观点是他们完全相反,并且有相反的行为.因此,它们不属于同一类.

您能举例说明您将在Boolean课堂上实施哪种常见行为?我什么都想不到.

让我们只看行为TrueClass,并FalseClass有:有完全4分的方法存在.不再.在每一种情况下,这两种方法恰恰相反.你怎么以及为什么把它放在一个班级?

以下是您实现所有这些方法的方法:

class TrueClass
  def &(other)
    other
  end

  def |(_)
    self
  end

  def ^(other)
    !other
  end

  def to_s
    'true'
  end
end
Run Code Online (Sandbox Code Playgroud)

而现在反过来说:

class FalseClass
  def &(_)
    self
  end

  def |(other)
    other
  end

  def ^(other)
    other
  end

  def to_s
    'false'
  end
end
Run Code Online (Sandbox Code Playgroud)

诚然,在Ruby中,有许多"魔法"在幕后发生,并且实际上TrueClass并没有被FalseClass解释器处理,而是硬连接到解释器中.这样的东西if,&&,||!.然而,在Smalltalk,从中红宝石借了很多,包括概念FalseClassTrueClass,所有这些都为实现方法,以及,你可以做同样的事情在Ruby中:

class TrueClass
  def if
    yield
  end

  def ifelse(then_branch=->{}, _=nil)
    then_branch.()
  end

  def unless
  end

  def unlesselse(_=nil, else_branch=->{})
    ifelse(else_branch, _)
  end

  def and
    yield
  end

  def or
    self
  end

  def not
    false
  end
end
Run Code Online (Sandbox Code Playgroud)

反过来说:

class FalseClass
  def if
  end

  def ifelse(_=nil, else_branch=->{})
    else_branch.()
  end

  def unless
    yield
  end

  def unlesselse(unless_branch=->{}, _=nil)
    ifelse(_, unless_branch)
  end

  def and
    self
  end

  def or
    yield
  end

  def not
    true
  end
end
Run Code Online (Sandbox Code Playgroud)

几年前,我写这篇文章只是为了好玩甚至发表它.除了语法看起来不同的事实,因为Ruby使用特殊运算符而我只使用方法,它的行为与Ruby的内置运算符完全相同.事实上,我实际上采用了RubySpec一致性测试套件并将其移植到我的语法中并且它通过了.

  • 类的目的是将类似的对象组合在一起(除此之外).我同意 - 而且这两个类具有完全相同的四种方法的事实告诉我,它们可能具有相同的类型.他们不共享任何实现是方法继承问题,而不是键入问题. (13认同)
  • 谢谢,您的评论非常广泛.我已经给出了一个常见行为的例子 - 字符串解析,如Boolean.parse("true")=> true.你有一个观点,他们有4种方法,他们做相反的事情.然而我不能承认它们不相似; 毕竟,`true.methods == false.methods`.方法方面,步行和听起来像鸭子. (9认同)
  • @alexloh:我从来没说过他们没有相同的类型.我同意你的意见:他们*做*有相同的类型.但这与他们的类没有任何关系:Ruby是一种面向对象的语言.在面向对象的语言中,对象的类型是由其协议定义的,而不是其类,不像ADT导向的语言,如Java,C#或C++,其中类*是*类型,但是不适用于Ruby,因为它不是面向ADT的OO.在面向对象的语言中,类的目的是实现共享,但是`true`和`false`*不共享任何实现. (5认同)

kik*_*ito 21

似乎Matz本人在2004 年的邮件列表消息中回答了这个问题.

他的答案的简短版本:"现在它工作正常,添加布尔没有任何优势".

就个人而言,我不同意这一点; 前面提到的"字符串解析"就是一个例子.另一个是当你根据类型对变量应用不同的处理时,(即一个yml解析器)具有"布尔"类是很方便的 - 它会删除一个"if".它看起来也更正确,但那是个人观点.

  • 我不知道我怎么做.我知道课程是开放的但是......我不确定他们的等级是什么.正确知道TrueClass和FalseClass直接来自Object.我必须在两者之间插入我的布尔类.不要认为它可能,但如果你证明我错了会很高兴. (5认同)
  • @kikito:我想可以用模块完成.见http://www.ruby-forum.com/topic/60154#56346:module Boolean; 结束[true,false] .each do | obj | obj.extend(布尔)结束 (3认同)
  • 在我看来,将TrueClass和FalseClass都作为布尔的子类将为您提供两全其美的优势:针对其不同行为的不同类,但是您可以添加常见行为/实现的公共基类.它还可以让你做像true.is_a这样的事情吗?布尔,感觉他们目前缺少.但就像@kikito所说,这必须在语言层面进行改变; 我们不能在运行时更改类的超类. (2认同)

ste*_*lag 6

Ruby 论坛 (2013)上引用 Matz :

...没有什么是真的和假的共同共享,因此没有布尔类。除此之外,在 Ruby 中,一切都表现为布尔值......