Ruby "nesne referansıyla geç" kullanıyor
(Python'un terminolojisini kullanarak.)
Ruby'nin "değere göre geç" veya "referansla geç" kullandığını söylemek, yardımcı olacak kadar açıklayıcı değildir. Çoğu insanın bugünlerde bildiği gibi, terminolojinin ("değer" ve "referans") C ++ 'dan geldiğini düşünüyorum.
C ++ 'da, "değere göre geç", işlevin değişkenin bir kopyasını aldığı ve kopyadaki herhangi bir değişikliğin orijinali değiştirmediği anlamına gelir. Bu nesneler için de geçerlidir. Bir nesne değişkenini değere göre iletirseniz, tüm nesne (tüm üyeleri dahil) kopyalanır ve üyelerde yapılan değişiklikler orijinal nesnedeki üyeleri değiştirmez. (İşaretçiyi değere göre iletmek farklıdır, ancak Ruby'nin zaten işaretçileri yoktur, AFAIK.)
class A {
public:
int x;
};
void inc(A arg) {
arg.x++;
printf("in inc: %d\n", arg.x); // => 6
}
void inc(A* arg) {
arg->x++;
printf("in inc: %d\n", arg->x); // => 1
}
int main() {
A a;
a.x = 5;
inc(a);
printf("in main: %d\n", a.x); // => 5
A* b = new A;
b->x = 0;
inc(b);
printf("in main: %d\n", b->x); // => 1
return 0;
}
Çıktı:
in inc: 6
in main: 5
in inc: 1
in main: 1
C ++ 'da "referansla geç", işlevin orijinal değişkene eriştiği anlamına gelir. Tamamen yeni bir değişmez tamsayı atayabilir ve orijinal değişken de bu değere sahip olacaktır.
void replace(A &arg) {
A newA;
newA.x = 10;
arg = newA;
printf("in replace: %d\n", arg.x);
}
int main() {
A a;
a.x = 5;
replace(a);
printf("in main: %d\n", a.x);
return 0;
}
Çıktı:
in replace: 10
in main: 10
Bağımsız değişken bir nesne değilse Ruby, değere göre pass değerini (C ++ anlamında) kullanır. Ancak Ruby'de her şey bir nesnedir, bu yüzden Ruby'deki C ++ anlamında gerçekten değere göre geçiş yoktur.
Ruby'de, "nesne referansıyla geç" (Python'un terminolojisini kullanmak için) kullanılır:
- İşlev içinde, nesnenin üyelerinden herhangi birine kendilerine yeni değerler atanabilir ve bu değişiklikler işlev döndükten sonra da devam eder. *
- İşlev içinde, değişkene tamamen yeni bir nesne atamak değişkenin eski nesneye başvurmayı durdurmasına neden olur. Ancak işlev döndükten sonra, orijinal değişken yine de eski nesneye başvurur.
Bu nedenle Ruby, C ++ anlamında "referansla geç" işlevini kullanmaz. Eğer öyleyse, fonksiyonun içindeki bir değişkene yeni bir nesne atamak, fonksiyon geri döndükten sonra eski nesnenin unutulmasına neden olur.
class A
attr_accessor :x
end
def inc(arg)
arg.x += 1
puts arg.x
end
def replace(arg)
arg = A.new
arg.x = 3
puts arg.x
end
a = A.new
a.x = 1
puts a.x # 1
inc a # 2
puts a.x # 2
replace a # 3
puts a.x # 2
puts ''
def inc_var(arg)
arg += 1
puts arg
end
b = 1 # Even integers are objects in Ruby
puts b # 1
inc_var b # 2
puts b # 1
Çıktı:
1
2
2
3
2
1
2
1
* Bu nedenle, Ruby'de, bir işlev içindeki bir nesneyi değiştirmek ancak işlev döndüğünde bu değişiklikleri unutmak istiyorsanız, kopyada geçici değişikliklerinizi yapmadan önce nesnenin bir kopyasını açıkça oluşturmanız gerekir.