summaryrefslogtreecommitdiff
path: root/doc/implicit_conversion.rdoc
blob: 0c2a1d4971309a2670ee6bc7d83f24fedd6644a2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
== 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
        [: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 <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)