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
Post a Comment