math - What does the + method in Ruby do, exactly? -
imagine want write own math operators "+"
the simple version be:
def plus(a,b) return a+b end
but not real "+" does.
i want 3.add(4) # =>7
how tell ruby take object used method on?
i tried
def add(c) return self+c end
but error message:
:in <main>': private method
add' called 3:fixnum (nomethoderror)
the problem
you defined method:
def add(c) return self + c end
and attempted use thus:
3.add(4) #=> nomethoderror: private method `add' called 3:fixnum
understanding error message
this error message tells problem is. think problem don't understand how ruby invokes methods on objects.
when ruby sees 3.add(4)
first looks @ receiver, 3
, , determines:
3.class #=> fixnum
this tells method add
defined: in class fixnum
or in 1 of fixnum
's ancestor's classes or modules.
so looks there, doesn't find it, , issues error message. can confirm it's not there:
fixnum.instance_methods.include?(:add) #=> false
so add
defined?
you did define it, though, it? let's find out:
method(:add).owner #=> object object.instance_methods.include?(:add) #=> false
object.instance_methods
returns array of of public instance methods defined on object
, object
's ancestors. add
not among those, conclude add
protected or private method:
object.protected_instance_methods.include?(:add) #=> false object.private_instance_methods.include?(:add) #=> true
let's try invoking method on instance of object
:
object.new.add(4) #=> nomethoderror: # private method `add' called #<object:0x007fdb6a27fa68>
that makes sense, considering object#add
private. can, invoke private methods object#send:
object.new.send(:add,4) #nomethoderror: undefined method `+' #<object:0x007fdb6a28e068>
as exercise, make sure understand steps ruby took led raising exception (that instance method +
not defined on object
, or equivalently, instance of object
not have method +
).
by way, did define add
? that, mean what value of self
when defined it? let's see:
self #=> main self.class #=> object
we see add
must defined on class receiver instance. (a mouthful, yes, it's important, make sure understand that).
why object#add
private rather public?
consider:
def greet puts 'hi' end class end a.private_instance_methods.include?(:add) #=> true a.new.send(:greet) #=> 'hi'
the because a
inherits greet
object
:
a.ancestors.include?(object) #=> true
if object#greet
public, every built-in class , every class define have public instance method greet
. result in great deal of misery. (suppose had method great
, mistyped greet
!) private greet
cause trouble.)
where should add
defined?
since add.class => fixnum
, define thus:
class fixnum def add(other) self + other end end fixnum.instance_methods.include?(:add) #=> true 3.add(4) #=> 7
had included line puts "self#{self}"
after class fixnum
have printed "fixnum". salting code puts
statements show value of self
helps in understanding what's going on.
one last thing:
method(:add).owner #=> nameerror: undefined method `add' class `object'
why did not return fixnum
? since method
has no explicit receiver (i.e., no xx.method
), ruby assumes receiver self
, here is:
self #=> main
so looks method method
in self.class => object
, , know finds (or, should say, doesn't find). instead, need write:
fixnum.instance_method(:add).owner #=> fixnum
or
3.method(:add).owner #=> fixnum
here 3
can of course replaced instance of fixnum
.
note i've simplified explanation somewhat. in searching method, ruby looks in receiver's singleton class. not issue immediate objects (numbers, symbols, true
, false
, nil
), however, not have singleton classes:
3.singleton_class #=> typeerror: can't define singleton
by contrast, example:
[1,2].singleton_class #=> #<class:#<array:0x007fbcf18c01a8>>
Comments
Post a Comment