2020-04-23 11:46:20 +03:00
|
|
|
== Implicit Conversions
|
|
|
|
|
|
|
|
Some Ruby methods accept one or more objects
|
|
|
|
that can be either:
|
|
|
|
* <i>Of a given class</i>, and so accepted as is.
|
|
|
|
* <i>Implicitly convertible to that class</i>, 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 <i>Array-convertible object</i> is an object that:
|
|
|
|
* Has instance method +to_ary+.
|
|
|
|
* The method accepts no arguments.
|
|
|
|
* The method returns an object +obj+ for which <tt>obj.kind_of?(Array)</tt> returns +true+.
|
|
|
|
|
|
|
|
The examples in this section use method <tt>Array#replace</tt>,
|
|
|
|
which accepts an Array-convertible argument.
|
|
|
|
|
|
|
|
This class is Array-convertible:
|
|
|
|
|
|
|
|
class ArrayConvertible
|
|
|
|
def to_ary
|
2020-05-16 00:11:42 +03:00
|
|
|
[:foo, 'bar', 2]
|
2020-04-23 11:46:20 +03:00
|
|
|
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)
|
2020-05-16 00:11:42 +03:00
|
|
|
[:foo, 'bar', 2]
|
2020-04-23 11:46:20 +03:00
|
|
|
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 <i>Hash-convertible object</i> is an object that:
|
|
|
|
* Has instance method +to_hash+.
|
|
|
|
* The method accepts no arguments.
|
|
|
|
* The method returns an object +obj+ for which <tt>obj.kind_of?(Hash)</tt> returns +true+.
|
|
|
|
|
|
|
|
The examples in this section use method <tt>Hash#merge</tt>,
|
|
|
|
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 <i>Integer-convertible object</i> is an object that:
|
|
|
|
* Has instance method +to_int+.
|
|
|
|
* The method accepts no arguments.
|
|
|
|
* The method returns an object +obj+ for which <tt>obj.kind_of?(Integer)</tt> returns +true+.
|
|
|
|
|
|
|
|
The examples in this section use method <tt>Array.new</tt>,
|
|
|
|
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 <i>String-convertible object</i> is an object that:
|
|
|
|
* Has instance method +to_str+.
|
|
|
|
* The method accepts no arguments.
|
|
|
|
* The method returns an object +obj+ for which <tt>obj.kind_of?(String)</tt> returns +true+.
|
|
|
|
|
|
|
|
The examples in this section use method <tt>String::new</tt>,
|
|
|
|
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)
|