This page contains automated test results for code from O'Reilly's Ruby Cookbook. If this code looks interesting or useful, you might want to buy the whole book.
Simulating a Subclass of Fixnum | ||
---|---|---|
Code | Expected | Actual |
require 'delegate' class HexNumber < DelegateClass(Fixnum) # The string representations of this class are hexadecimal numbers. def to_s sign = self < 0 ? "-" : "" hex = abs.to_s(16) "#{sign}0x#{hex}" end def inspect to_s end end HexNumber.new(10) |
0xa | 0xa |
HexNumber.new(-10) |
-0xa | -0xa |
HexNumber.new(1000000) |
0xf4240 | 0xf4240 |
HexNumber.new(1024 ** 10) |
0x10000000000000000000000000 | 0x10000000000000000000000000 |
HexNumber.new(10).succ |
11 | 11 |
HexNumber.new(10) * 2 |
20 | 20 |
100.object_id |
201 | 201 |
(10 * 10).object_id |
201 | 201 |
Fixnum.new(100) |
NoMethodError: undefined method `new' for Fixnum:Class ... |
NoMethodError: undefined method `new' for Fixnum:Class from (irb):21 |
(10 ** 20).object_id |
-606073730 | -606073880 |
((10 ** 19) * 10).object_id |
-606079360 | -606079510 |
Bignum.new(10 ** 20) |
NoMethodError: undefined method `new' for Bignum:Class ... |
NoMethodError: undefined method `new' for Bignum:Class from (irb):24 |
HexNumber.new(10) * 2 |
20 | 20 |
HexNumber.new(10) + HexNumber.new(200) |
210 | 210 |
require 'rubygems' require 'facet/basicobject' class BetterHexNumber < BasicObject def initialize(integer) @value = integer end # Delegate all methods to the stored integer value. If the result is a # Integer, transform it into a BetterHexNumber object. If it's an # enumerable containing Integers, transform it into an enumerable # containing BetterHexNumber objects. def method_missing(m, *args) super unless @value.respond_to?(m) hex_args = args.collect do |arg| arg.kind_of?(BetterHexNumber) ? arg.to_int : arg end result = @value.send(m, *hex_args) return result if m == :coerce case result when Integer BetterHexNumber.new(result) when Array result.collect do |element| element.kind_of?(Integer) ? BetterHexNumber.new(element) : element end else result end end # We don't actually define any of the Fixnum methods in this class, # but from the perspective of an outside object we do respond to # them. What outside objects don't know won't hurt them, so we'll # claim that we actually implement the same methods as our delegate # object. Unless this method is defined, features like ranges won't # work. def respond_to?(method_name) super or @value.respond_to? method_name end # Convert the number to a hex string, ignoring any other base # that might have been passed in. def to_s(*args) hex = @value.abs.to_s(16) sign = self < 0 ? "-" : "" "#{sign}0x#{hex}" end def inspect to_s end end hundred = BetterHexNumber.new(100) |
0x64 | 0x64 |
hundred + 5 |
0x69 | 0x69 |
hundred + BetterHexNumber.new(5) |
0x69 | 0x69 |
hundred.succ |
0x65 | 0x65 |
hundred / 5 |
0x14 | 0x14 |
hundred * -10 |
-0x3e8 | -0x3e8 |
hundred.divmod(3) |
[0x21, 0x1] | [0x21, 0x1] |
(hundred...hundred+3).collect |
[0x64, 0x65, 0x66] | [0x64, 0x65, 0x66] |
hundred.class |
Fixnum | Fixnum |
hundred.respond_to? :succ |
true | true |
hundred.is_a? Fixnum |
false | false |