summaryrefslogtreecommitdiff log msg author committer range
path: root/doc/syntax/methods.rdoc
blob: 70a916387d4ecd0af10568431e79b472c76a4dbe (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 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 ``` ``````= Methods Methods implement the functionality of your program. Here is a simple method definition: def one_plus_one 1 + 1 end A method definition consists of the +def+ keyword, a method name, the body of the method, then the +end+ keyword. When called the method will execute the body of the method. This method returns +2+. == Return values By default, a method returns the last expression that was evaluated in the body of the method. In the example above, the last (and only) expression evaluated was the simple sum 1 + 1. The +return+ keyword can be used to make it explicit that a method returns a value. def one_plus_one return 1 + 1 end It can also be used to make a method return before the last expression is evaluated. def two_plus_two return 2 + 2 1 + 1 # this expression is never evaluated end == Scope The standard syntax to define a method: def my_method # ... end adds the method to a class. You can define an instance method on a specific class with the +class+ keyword: class C def my_method # ... end end A method may be defined on another object. You may define a "class method" (a method that is defined on the class, not an instance of the class) like this: class C def self.my_method # ... end end However, this is simply a special case of a greater syntactical power in Ruby, the ability to add methods to any object. Classes are objects, so adding class methods is simply adding methods to the Class object. The syntax for adding a method to an object is as follows: greeting = "Hello" def greeting.broaden self + ", world!" end greeting.broaden # returns "Hello, world!" +self+ is a keyword referring to the current object under consideration by the compiler, which might make the use of +self+ in defining a class method above a little clearer. Indeed, the example of adding a +hello+ method to the class +String+ can be rewritten thus: def String.hello "Hello, world!" end A method defined like this is called a "singleton method". +broaden+ will only exist on the string instance +greeting+. Other strings will not have +broaden+. == Overriding When Ruby encounters the +def+ keyword, it doesn't consider it an error if the method already exists: it simply redefines it. This is called _overriding_. Rather like extending core classes, this is a potentially dangerous ability, and should be used sparingly because it can cause unexpected results. For example, consider this irb session: >> "43".to_i => 43 >> class String >> def to_i >> 42 >> end >> end => nil >> "43".to_i => 42 This will effectively sabotage any code which makes use of the method String#to_i to parse numbers from strings. == Arguments A method may accept arguments. The argument list follows the method name: def add_one(value) value + 1 end When called, the user of the +add_one+ method must provide an argument. The argument is a local variable in the method body. The method will then add one to this argument and return the value. If given +1+ this method will return +2+. The parentheses around the arguments are optional: def add_one value value + 1 end Multiple arguments are separated by a comma: def add_values(a, b) a + b end When called, the arguments must be provided in the exact order. In other words, the arguments are positional. === Default Values Arguments may have default values: def add_values(a, b = 1) a + b end The default value does not need to appear first, but arguments with defaults must be grouped together. This is ok: def add_values(a = 1, b = 2, c) a + b + c end This will raise a SyntaxError: def add_values(a = 1, b, c = 1) a + b + c end === Array/Hash Argument Prefixing an argument with * causes any remaining arguments to be converted to an Array: def gather_arguments(*arguments) p arguments end gather_arguments 1, 2, 3 # prints [1, 2, 3] The array argument must be the last positional argument, it must appear before any keyword arguments. The array argument will capture a Hash as the last entry if a hash was sent by the caller after all positional arguments. gather_arguments 1, a: 2 # prints [1, {:a=>2}] However, this only occurs if the method does not declare any keyword arguments. def gather_arguments_keyword(*positional, keyword: nil) p positional: positional, keyword: keyword end gather_arguments_keyword 1, 2, three: 3 #=> raises: unknown keyword: three (ArgumentError) Also, note that a bare * can be used to ignore arguments: def ignore_arguments(*) end === Keyword Arguments Keyword arguments are similar to positional arguments with default values: def add_values(first: 1, second: 2) first + second end Arbitrary keyword arguments will be accepted with **: def gather_arguments(first: nil, **rest) p first, rest end gather_arguments first: 1, second: 2, third: 3 # prints 1 then {:second=>2, :third=>3} When calling a method with keyword arguments the arguments may appear in any order. If an unknown keyword argument is sent by the caller an ArgumentError is raised. When mixing keyword arguments and positional arguments, all positional arguments must appear before any keyword arguments. == Exception Handling Methods have an implied exception handling block so you do not need to use +begin+ or +end+ to handle exceptions. This: def my_method begin # code that may raise an exception rescue # handle exception end end May be written as: def my_method # code that may raise an exception rescue # handle exception end If you wish to rescue an exception for only part of your method use +begin+ and +end+. For more details see the page on {Exception Handling}[rdoc-ref:doc/syntax/exceptions.rdoc]. ``````