From: Adam Prescott Date: 2013-03-27T21:56:50+09:00 Subject: Re: Why don't TrueClass and FalseClass share a common Boolean ancestor On 27 March 2013 11:56, Rob N. wrote: > Both TrueClass and FalseClass inherit directly from the Object class. > They share a common structure and do very similar jobs. So why don't > they share a common parent between them and Object? BooleanClass > perhaps? I'd be curious to know what exactly you're testing, and why you need to deal with true and false as specific values. Here's my justification, although if anyone finds flaws, please point them out! (There might be better arguments than this.) All objects that are not nil or false evaluate as truthy. s = "foo" puts "You'll see this." if s The presence of a Boolean starts to suggest code like this: do_something(arg) if arg.class == Boolean This goes against duck typing. Let's look at Integer, for instance. Integer wraps Fixnum and Bignum, but you *shouldn't* really ever do this: process_number(arg) if arg.is_a?(Integer) Instead you should allow objects to indicate they have Integer representations, without forcing them to subclass: class BankBalance # Note this does not subclass Integer def initialize(amount) @amount = amount end def to_int @amount end end (First example off the top of my head. Might have problems, but treat as illustrative.) Now any code that wants to deal with some notion of an integer can rely on BankBalance instances without any checks: do_something(number.to_int) BankBalance doesn't implement an Integer so it shouldn't subclass Integer, but by defining to_int, the class is saying it can act like one in a certain way; the net result being that code can skip checking implementation details. Note that to_int is different from to_i. to_i is an explicit conversion to an integer, but to_int is intended to give the message: "I act like an Integer." Similarly: to_str for acting like a String, distinct from explicit conversion with to_s. So with that in mind, you might imagine Boolean-ish duck typing based on something like to_bool, right? class TrueClass def to_bool true end end class FalseClass def to_bool false end end def NilClass def to_bool false end end But then (Basic)Object would need to define it so that all non-nil, non-false objects come back as truthy: class Object def to_bool true end end But then you might hit a lot of confusion if something decides to define to_bool as false: suddenly Ruby's contract of "non-nil, non-false values are truthy" can have extra clauses added to it. And, what have you gained? if arg.to_bool # do stuff end Ruby gives you this: if arg # do stuff end So I guess to summarise the above: * Duck typing. * It's built in for you implicitly.