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 methodadd' 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

Popular posts from this blog

asp.net mvc - SSO between MVCForum and Umbraco7 -

Python Tkinter keyboard using bind -

ubuntu - Selenium Node Not Connecting to Hub, Not Opening Port -