Ruby ใช้ "การอ้างอิงผ่านวัตถุ"
(การใช้คำศัพท์ของ Python)
ในการพูดว่า Ruby ใช้ "pass by value" หรือ "pass by reference" นั้นไม่ได้มีความหมายเพียงพอที่จะเป็นประโยชน์ ฉันคิดว่าเป็นคนส่วนใหญ่รู้ว่าวันนี้คำศัพท์นั้น ("ค่า" กับ "การอ้างอิง") มาจาก C ++
ใน C ++ "pass by value" หมายถึงฟังก์ชั่นได้รับสำเนาของตัวแปรและการเปลี่ยนแปลงใด ๆ ในการคัดลอกจะไม่เปลี่ยนต้นฉบับ นั่นเป็นความจริงสำหรับวัตถุด้วย หากคุณส่งตัวแปรออบเจ็กต์ตามค่าดังนั้นออบเจ็กต์ทั้งหมด (รวมถึงสมาชิกทั้งหมด) จะถูกคัดลอกและการเปลี่ยนแปลงใด ๆ กับสมาชิกจะไม่เปลี่ยนสมาชิกเหล่านั้นบนออบเจ็กต์ดั้งเดิม (มันแตกต่างกันถ้าคุณผ่านตัวชี้ตามค่า แต่ Ruby ไม่มีตัวชี้ 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;
}
เอาท์พุท:
in inc: 6
in main: 5
in inc: 1
in main: 1
ใน C ++ "pass by reference" หมายถึงฟังก์ชั่นสามารถเข้าถึงตัวแปรต้นฉบับได้ มันสามารถกำหนดจำนวนเต็มตามตัวอักษรใหม่ทั้งหมดและตัวแปรเดิมจะมีค่านั้นด้วย
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;
}
เอาท์พุท:
in replace: 10
in main: 10
Ruby ใช้ pass by value (ในความหมาย C ++) หากอาร์กิวเมนต์ไม่ใช่วัตถุ แต่ใน Ruby ทุกอย่างเป็นวัตถุดังนั้นจึงไม่มีคุณค่าในความรู้สึกของ C ++ ใน Ruby
ใน Ruby มีการใช้ "pass by object reference" (เพื่อใช้คำศัพท์ของ Python):
- ภายในฟังก์ชั่นสมาชิกของวัตถุสามารถกำหนดค่าใหม่ให้กับพวกเขาและการเปลี่ยนแปลงเหล่านี้จะยังคงอยู่หลังจากที่ฟังก์ชั่นกลับมา *
- ภายในฟังก์ชันการกำหนดวัตถุใหม่ทั้งหมดให้กับตัวแปรทำให้ตัวแปรหยุดการอ้างอิงวัตถุเก่า แต่หลังจากฟังก์ชั่นกลับมาตัวแปรเดิมจะยังคงอ้างอิงวัตถุเก่า
ดังนั้น Ruby ไม่ใช้ "pass by reference" ในความหมาย C ++ ถ้าเป็นเช่นนั้นการกำหนดวัตถุใหม่ให้กับตัวแปรภายในฟังก์ชั่นจะทำให้วัตถุเก่าถูกลืมหลังจากฟังก์ชันส่งคืน
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
เอาท์พุท:
1
2
2
3
2
1
2
1
* นี่คือเหตุผลว่าทำไมใน Ruby หากคุณต้องการแก้ไขวัตถุภายในฟังก์ชั่น แต่ลืมการเปลี่ยนแปลงเหล่านั้นเมื่อฟังก์ชั่นส่งคืนดังนั้นคุณต้องทำสำเนาของวัตถุอย่างชัดเจนก่อนทำการเปลี่ยนแปลงสำเนาชั่วคราว