== Implicit Conversions
Some Ruby methods accept one or more objects
that can be either:
* Of a given class, and so accepted as is.
* Implicitly convertible to that class, in which case
the called method converts the object.
For each of the relevant classes, the conversion is done by calling
a specific conversion method:
* Array: +to_ary+
* Hash: +to_hash+
* Integer: +to_int+
* String: +to_str+
=== Array-Convertible Objects
An Array-convertible object is an object that:
* Has instance method +to_ary+.
* The method accepts no arguments.
* The method returns an object +obj+ for which obj.kind_of?(Array) returns +true+.
The Ruby core class that satisfies these requirements is:
* Array
The examples in this section use method Array#replace,
which accepts an Array-convertible argument.
This class is Array-convertible:
class ArrayConvertible
def to_ary
[:foo, 'bar', 2]
end
end
a = []
a.replace(ArrayConvertible.new) # => [:foo, "bar", 2]
This class is not Array-convertible (no +to_ary+ method):
class NotArrayConvertible; end
a = []
# Raises TypeError (no implicit conversion of NotArrayConvertible into Array)
a.replace(NotArrayConvertible.new)
This class is not Array-convertible (method +to_ary+ takes arguments):
class NotArrayConvertible
def to_ary(x)
[:foo, 'bar', 2]
end
end
a = []
# Raises ArgumentError (wrong number of arguments (given 0, expected 1))
a.replace(NotArrayConvertible.new)
This class is not Array-convertible (method +to_ary+ returns non-Array):
class NotArrayConvertible
def to_ary
:foo
end
end
a = []
# Raises TypeError (can't convert NotArrayConvertible to Array (NotArrayConvertible#to_ary gives Symbol))
a.replace(NotArrayConvertible.new)
=== Hash-Convertible Objects
A Hash-convertible object is an object that:
* Has instance method +to_hash+.
* The method accepts no arguments.
* The method returns an object +obj+ for which obj.kind_of?(Hash) returns +true+.
The Ruby core class that satisfies these requirements is:
* Hash
The examples in this section use method Hash#merge,
which accepts a Hash-convertible argument.
This class is Hash-convertible:
class HashConvertible
def to_hash
{foo: 0, bar: 1, baz: 2}
end
end
h = {}
h.merge(HashConvertible.new) # => {:foo=>0, :bar=>1, :baz=>2}
This class is not Hash-convertible (no +to_hash+ method):
class NotHashConvertible; end
h = {}
# Raises TypeError (no implicit conversion of NotHashConvertible into Hash)
h.merge(NotHashConvertible.new)
This class is not Hash-convertible (method +to_hash+ takes arguments):
class NotHashConvertible
def to_hash(x)
{foo: 0, bar: 1, baz: 2}
end
end
h = {}
# Raises ArgumentError (wrong number of arguments (given 0, expected 1))
h.merge(NotHashConvertible.new)
This class is not Hash-convertible (method +to_hash+ returns non-Hash):
class NotHashConvertible
def to_hash
:foo
end
end
h = {}
# Raises TypeError (can't convert NotHashConvertible to Hash (ToHashReturnsNonHash#to_hash gives Symbol))
h.merge(NotHashConvertible.new)
=== Integer-Convertible Objects
An Integer-convertible object is an object that:
* Has instance method +to_int+.
* The method accepts no arguments.
* The method returns an object +obj+ for which obj.kind_of?(Integer) returns +true+.
The Ruby core classes that satisfy these requirements are:
* Integer
* Float
* Complex
* Rational
The examples in this section use method Array.new,
which accepts an Integer-convertible argument.
This user-defined class is Integer-convertible:
class IntegerConvertible
def to_int
3
end
end
a = Array.new(IntegerConvertible.new).size
a # => 3
This class is not Integer-convertible (method +to_int+ takes arguments):
class NotIntegerConvertible
def to_int(x)
3
end
end
# Raises ArgumentError (wrong number of arguments (given 0, expected 1))
Array.new(NotIntegerConvertible.new)
This class is not Integer-convertible (method +to_int+ returns non-Integer):
class NotIntegerConvertible
def to_int
:foo
end
end
# Raises TypeError (can't convert NotIntegerConvertible to Integer (NotIntegerConvertible#to_int gives Symbol))
Array.new(NotIntegerConvertible.new)
=== String-Convertible Objects
A String-convertible object is an object that:
* Has instance method +to_str+.
* The method accepts no arguments.
* The method returns an object +obj+ for which obj.kind_of?(String) returns +true+.
The Ruby core class that satisfies these requirements is:
* String
The examples in this section use method String::new,
which accepts a String-convertible argument.
This class is String-convertible:
class StringConvertible
def to_str
'foo'
end
end
String.new(StringConvertible.new) # => "foo"
This class is not String-convertible (no +to_str+ method):
class NotStringConvertible; end
# Raises TypeError (no implicit conversion of NotStringConvertible into String)
String.new(NotStringConvertible.new)
This class is not String-convertible (method +to_str+ takes arguments):
class NotStringConvertible
def to_str(x)
'foo'
end
end
# Raises ArgumentError (wrong number of arguments (given 0, expected 1))
String.new(NotStringConvertible.new)
This class is not String-convertible (method +to_str+ returns non-String):
class NotStringConvertible
def to_str
:foo
end
end
# Raises TypeError (can't convert NotStringConvertible to String (NotStringConvertible#to_str gives Symbol))
String.new(NotStringConvertible.new)