Użycie self, problem

Witam, mam taki problem. oto kawałek kodu:

def add(n)
self + n
end
puts 2.add(2)

według książki z której się ucze powinno zwrócić “4” a zwraca to:
*NoMethodError: private method dupa' called for 2.0:Float from (irb):71 from /home/dominik/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/railties-4.0.0.beta1/lib/rails/commands/console.rb:88:instart’
from /home/dominik/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/railties-4.0.0.beta1/lib/rails/commands/console.rb:9:in start' from /home/dominik/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/railties-4.0.0.beta1/lib/rails/commands.rb:64:in<top (required)>’
from bin/rails:4:in require'* from bin/rails:4:in

może mi ktoś wytłumaczyć dlaczego? jestem zielonek i szukając w google i tu nie znalazłem odpowiedzi :smile:

Pozdrawiam.

P.S. z racji tego że jest to mój pierwszy post tutaj jeżeli nieprzestrzegam nim jakichś zasad proszę o zwrócenie uwagi ;]

musisz definiować tę metodę w odpowiedniej klasie, np.:

irb(main):087:0> class Fixnum
irb(main):088:1>   def add(n)
irb(main):089:2>     self + n
irb(main):090:2>   end
irb(main):091:1> end
=> :add
irb(main):092:0> 2.add 3
=> 5

rozumiem :slight_smile: a dlaczego książka o tym nie mówi? :slight_smile: dodam że książka z której się uczę to: “ruby, szybki start” Larry Ullman, i jak do tej pory jeszcze nie miałem nic z klasami i “on” tutaj wrzucając przykłady nie ma takiego probelmu. :wink: czyżby coś się zminiło w Ruby2.0? bo taki mam a książka jest na Rubym1.9.

Dopisane jest w ksiązce:
Metody zdefiniowane poza wszelkimi klasami takie jak wszystkie, które zostały przeddstawione w tym rozdziale, stają się częścią klasy Ruby o nazwie Object . Z tego powodu można jes stosować podobnie jak funkcje globalne do dowolnego obiektu.

sorry, wprowadziłem Cię w błąd.

metoda dodana w IRB poza klasą jest dostępna wszędzie, dlatego definiując add możesz je wywołać na dowolnej klasie (w rzeczywistości rozszerzasz Object z którego prawie wszystko dziedziczy.)

Problem w tym że te metody są prywatne dlatego nie możesz ich wykonywać. Teoretycznie IRB powinno robić je publicznymi (według internetów), nie wiem dlaczego tak się nie dzieje (możliwe że w którejś wersji to zmienili).

żeby to obejść możesz zadeklarować metodę explicite publicznie, np.

irb(main):001:0> public def add(x); self + x; end
=> Object
irb(main):002:0> 3.add 2
=> 5

rozumiem, czyli ten problem dotyczy tylko IRB? :slight_smile: reszta będzie ok? jeżeli tak i nikt nie ma pomyslu dlaczego to jest private a nie public no to chyba nie ma co drążyć ;]

Dzięki za odpowiedź

Pozwolę sobie na kilka słów wyjaśniających. Każda metoda zdefiniowana w sposób globalny, niezależnie czy mówimy o irbie czy po prostu pliku, który zostanie załadowany przez ruby, będzie należeć do klasy Object i będzie metodą prywatną.

Jako, że uczysz się dopiero języka dobrze jest tego typu teorie umieć poprzeć eksperymentem.

> def foo
|   puts "foo"
| end
:foo
> method(:foo).owner
Object
> foo
foo
nil
> self.foo
NoMethodError: private method `foo' called for main:Object
	from (irb):6
	from /Users/radarek/.rbenv/versions/2.2.0/bin/irb:11:in `<main>'

(dlaczego samo “foo” zadziałało, a dlaczego już “self.foo” nie, dowiesz się czytając o poziomach dostępu do metod).

Dlaczego te metody są prywatne a nie publiczne? Przede wszystkim raczej nie chcielibyśmy by deklaracja globalnej metody rozszerzała interfejs publiczny każdej klasy (obiekt.puts "wtf"), prawda? O takich globalnych metodach myślimy raczej jak o funkcjach. Zatem gdy piszę “puts”, które wywołam w klasie “Foo”, raczej nie myślę “wywołuję metodę prywatną na instancji klasy Foo” tylko “wywołuję funkcję puts”.

Co do różnicy między irb a rubym - wątpię by kiedykolwiek była taka. Jeśli była to prędzej kopę lat temu co świadczyłoby o tym, że książka jest przestarzała.

Co do Twojego przykładu to raczej bym się spodziewał, że faktycznie ta metoda jest zdefiniowana w którejś z klas reprezentujących liczby. Więc albo coś pokiełbasiłeś, ale autor tej książki nie wiedział o czym pisze ;).

W rubym 1.9.3 i wcześniejszych wersjach metody, które definiowałeś nie były prywatne i ten kod działał. Bodaj od wersji 2.0.0 już tak nie jest i ten sam kod nie zadziała.

Masz rację, ale dotyczyło to tylko irba (sprawdziłem).

Dokładnie :slight_smile: To najbardziej interesowało Dominika. Odnośnie wykonywanie kodu to metody, które deklarujemy poza jakąkolwiek klasą mają modyfikator prywatny i nie możemy ich wywołać na rzecz innego obiektu. Niejawnie metoda ta jest wywoływana na rzecz obiektu ‘main’ (wywołaj puts self).

noo dokładnie mnie to interesowało. Bo książke mam z ruby 1.9 i zastanawiałem sie czy to po prostu się nie zmieniło w 2.0.

Noo jak narazie walcze z tym rubym, dużo jest jeszcze niejasności w tym ale idzie to do przodu :stuck_out_tongue: niestety nie jest to jeszcze etap gdzie można aplikować do jakiejś pracy podejrzewam. A szkoda bo mi praca potrzebna ;D