Jak przekazac do funkcji reference do obiektu? Wiem ze kazdy element w rubym jest obiektem, ale niewiele mi to pomaga bo nie wiem jak to zastosowac.
Potrzebna mi jest funkcja np:
def test(&pVar)
pVar = ‘dasasd’
return ‘ok’
end
Generalnie w Rubim działamy na referencji, ale gdy przekazujesz do swojej funkcji wartość bo, robisz w ten sposób jej kopię. Zatem podmiana tej wartości nie powoduje zmiany oryginalnego obiektu. Można uzyskać żądany przez Ciebie efekt, aczkolwiek nie jest to najładniejszy sposób :-). Moja propozycja na szybko:
[code]def fun1(b)
b = “dsadsa”
return “ok”
end
b = 1
a = fun1(b)
puts “a = #{a}, b = #{b}” #=> a = ok, b = 1
def fun2(b, binding)
eval(%{
b = “dsadsa”
}, binding)
return “ok”
end
b = 1
a = fun2(b, binding)
puts “a = #{a}, b = #{b}” #=> a = ok, b = dsadsa
b = 1
a = fun2(b, nil)
puts “a = #{a}, b = #{b}” #=> a = ok, b = 1[/code]
Odsyłam do manuala: ri Kernel#eval oraz ri Kernel#binding
Możesz także opakować swoją klasę jakąś klasą wrapperem i w niej trzymać referencję, która zostanie podmieniona.
[code]class Wrapper
attr_accessor :value
def initialize(value)
@value = value
end
end
def fun3(b)
b.value = “dsadsa”
return “ok”
end
b = Wrapper.new(1)
a = fun3(b)
puts “a = #{a}, b = #{b.value}” #=> ok, dsadsa[/code]
Generalnie o czymś takim jak przekazanie zmiennej przez referencje zapomnij :-). Zmieniaj po prostu stan przekazywanych obiektów.
Ja wolę myśleć o tym jak o wskaźnikach. Jeśli przekazuję coś do funkcji, to przekazuję wskaźnik na ten obiekt, jeśli zmienię wskaźnik w środku funkcji, to logicznym, że nie zmienię go na zewnątrz, jeśli jednak zmienię obiekt, na który wskaźnik wskazuje to wskaźnik z zewnątrz będzie wskazywał na ten obiekt.
rupert@laptop:~$ irb
irb(main):001:0> a = "aba"
=> "aba"
irb(main):002:0> b = "abba"
=> "abba"
irb(main):003:0> def m(o)
irb(main):004:1> o = "n"
irb(main):005:1> end
=> nil
irb(main):006:0> m(a)
=> "n"
irb(main):007:0> a
=> "aba"
irb(main):008:0> def m2(o)
irb(main):009:1> o.capitalize!
irb(main):010:1> end
=> nil
irb(main):011:0> m2(a)
=> "Aba"
irb(main):012:0> a
=> "Aba"
Ja wolę myśleć o tym jak o wskaźnikach. Jeśli przekazuję coś do funkcji, to przekazuję wskaźnik na ten obiekt, jeśli zmienię wskaźnik w środku funkcji, to logicznym, że nie zmienię go na zewnątrz, jeśli jednak zmienię obiekt, na który wskaźnik wskazuje to wskaźnik z zewnątrz będzie wskazywał na ten obiekt.[/quote]
Wydaje mi się, że to jest dokładnie to samo :). Podstaw za ‘wskaźnik’ słowo ‘referencja’ i zobacz, że sens jest zachowany.
[quote=sandmann]Mozna wtedy sobie rozszerztyc powiedzmy klasy String i FixNum o metde change_value! i wtedy po wywolaniu:
a = 5
def m(o)
a.change_value!(6)
end
m(a)
a bedzie wynosic 6.[/quote]
A próbowałeś tak zrobić? Bo dla klas, które podałeś jest to niewykonalne. Dlaczego? Ponieważ dajmy na to w klasie String nie da się podmienić “samego siebie” (self) na inny obiekt. Implementacja musiałaby wyglądać mniej więcej tak:
class String
def change_value(str)
self = str #nie przejdzie
end
end
a to niestety nie zadziała. Mało tego, obiekty liczbowe (FixNum) są niemutowalne, tzn raz utworzony obiekt nie zmienia swojego stanu i Ruby nie udostępnia metod, które je zmieniają.