2012-01-06 61 views
10

Bất cứ ai có thể mở rộng, sửa chữa hoặc xác minh những gì tôi cảm thấy đang xảy ra khi bạn chuyển đối số cho một phương thức trong Ruby. Có bất kỳ điểm nào trong số này sai không? Tôi có thiếu sót gì không?Các đối số được truyền cho các phương thức theo tham chiếu hay giá trị?

  • Mọi thứ trong Ruby là một đối tượng.
  • Biến là tham chiếu đến đối tượng
  • (Khi chuyển một biến vào phương thức): Tham số trong phương thức bắt biến là biến cục bộ cho phương thức đó. Tham số (biến cục bộ) bây giờ cũng có một tham chiếu đến cùng một đối tượng.
  • Tôi có thể thay đổi đối tượng (tại chỗ) và thay đổi này sẽ giữ khi phạm vi phương thức được thoát. Bất kỳ biến nào tham chiếu đối tượng này ngoài phạm vi phương thức sẽ phản ánh rằng đối tượng đã bị thay đổi.
  • Một nhiệm vụ mới cho tham số đó (biến địa phương) không thay đổi đối tượng gốc, do đó bất kỳ tham chiếu đến nó khi phương pháp rời khỏi phạm vi sẽ vẫn không thay đổi.
  • Nếu tôi chuyển một biến vào phương thức tham chiếu một số nguyên thì không có cách nào có hiệu quả khi phương thức đó thoát khỏi tôi có thể có biến đó tham chiếu đến một số nguyên mới.

Có cách nào để có một phương thức là một trong số các tham số của nó là Số nguyên không, thực hiện một số nội dung và có thể là một tác dụng phụ thay đổi giá trị, thay đổi đó được phản ánh khi phương thức thoát. Có lẽ tôi chỉ không nghĩ "cách Ruby".

+2

có thể trùng lặp của [void foo (int & x) -> Ruby? Chuyển số nguyên theo tham chiếu?] (Http://stackoverflow.com/questions/2650634/void-fooint-x-ruby-passing-integers-by-reference) – derekerdmann

Trả lời

20

Mọi thứ trong Ruby là một đối tượng.

Đóng đủ.

biến được tham chiếu đến đối tượng

số Một biến "tên" một đối tượng: khi một biến được đánh giá, nó đánh giá với đối tượng mà nó hiện "tên". Nội bộ này được thực hiện bằng cách "lưu trữ một con trỏ" (hoặc cơ chế tương đương) cho một đối tượng. (Mặc dù một thực hiện không cần phải luôn luôn sử dụng con trỏ: trong Ruby MRI, ví dụ, giá trị Fixnum thực sự tồn tại mà không một đối tượng thực sự.)

(Khi đi qua trong một biến thành một phương pháp): Tham số trong phương thức bắt biến là một biến cục bộ cho phương thức đó. Tham số (biến cục bộ) bây giờ cũng có một tham chiếu đến cùng một đối tượng.

No. Xem ở trên. Tuy nhiên, cả hai biến bây giờ đặt tên (hoặc "đánh giá") cùng một đối tượng. Các tham số được thông qua nội bộ sử dụng Call-by-Value - tức là, nội bộ, các con trỏ tới các đối tượng được chuyển - mặc dù Ruby có một thuật ngữ tôi cố gắng quảng bá khi tôi tìm thấy nó mô tả ngắn gọn hành vi.

Tôi có thể thay đổi đối tượng (tại chỗ) và thay đổi này sẽ giữ khi phạm vi phương thức được thoát. Bất kỳ biến nào tham chiếu đối tượng này ngoài phạm vi phương thức sẽ phản ánh rằng đối tượng đã bị thay đổi.

Có, một đối tượng là chính nó. Nếu bạn tắt tiếng đối tượng, bạn thay đổi đối tượng đó ở mọi nơi. Nhưng lưu ý: không biến nào trong số các biến được thay đổi. Cả hai biến bên trong và bên ngoài sẽ vẫn còn tên (hoặc "đánh giá") cùng một đối tượng.

Bài tập mới cho tham số đó (biến cục bộ) không thay đổi đối tượng gốc, do đó mọi tham chiếu đến đối tượng đó khi phương thức rời khỏi phạm vi sẽ không thay đổi.

Đúng. Nếu bạn gán một giá trị khác cho biến cục bộ mà bạn tạo, biến cục bộ, đặt tên cho một đối tượng khác. Ruby là không phảiCall-by-Reference do đó biến trong ngữ cảnh gọi điện không bị thay đổi.

Nếu tôi chuyển một biến vào phương thức tham chiếu một số nguyên, không có cách nào mà phương thức đó thoát khỏi tôi có thể có biến đó tham chiếu đến một số nguyên mới?

Biến số không bao giờ được chuyển. Biến được đánh giá đối tượng mà chúng đặt tên và các đối tượng đó được chuyển qua. Dù sao, chúng tôi biết rằng:

  1. Ruby là không Gọi theo tham chiếu và;
  2. Số nguyên (Fixnums) là không thay đổi

Như vậy:

x = 1 
y.foo(x) 

thể bao giờ thay đổi gì x tên, cũng không có thể nó thậm chí thay đổi các nội dung của tên đối tượng x (vì nó, cũng , không thay đổi). Ngay cả khi đối tượng mà x tên là có thể thay đổi, phương pháp không thể có thay đổi đối tượng x tên: nó chỉ có thể có đột biến các đối tượng đó là kết quả của việc đánh giá x.

Mã hóa vui vẻ.


Bây giờ, The Way Ruby - trong cuốn sách của tôi - sẽ được sử dụng một giá trị trả về tốt hơn mà vây tất cả trạng thái mới, và để cho người gọi đặt nó nơi nó cần phải đi :-)

Tất nhiên, đối tượng có thể thay đổi (bao gồm mảng đơn giản) cũng là một tùy chọn, nhưng đó là ick. Và, nếu có đủ trạng thái di chuyển cùng nhau, nó có thể là một ứng cử viên cho một lớp riêng biệt.


Là một lưu ý đóng cửa: Ruby hỗ trợ một khái niệm về đóng cửa, vì vậy nó có thể trong một lexically đặt phạm vi cách:

x = 1; (lamb­da {|a| x = a}).c­all(2); x // => 2 

(Điều này đã được hiển thị cho một lambda đơn giản, nhưng nó có thể thiết kế/thủ công một phương pháp để làm việc tương tự: trong tất cả các ví dụ phản hồi ngớ ngẩn như thế này, thì chính biến số bên ngoài biến số cần phải biết, vì không có cách nào cho lambda/phương thức tạo biến bên ngoài đặt tên cho đối tượng mới khác.)

+0

Cảm ơn bạn đã có câu trả lời tuyệt vời! Đối với ngữ nghĩa "tên" và "tham chiếu", tôi không hiểu sự khác biệt. Một biến "tên" một đối tượng ... điều này cho nó một "tham chiếu" đối tượng. Có thể "đặt tên" một đối tượng chứ không phải "tham chiếu" nó không? Có thể có một "tham chiếu" tới một đối tượng chứ không phải "tên" nó không? Có những ví dụ bạn có thể trỏ đến sơ đồ đó mối quan hệ này, và có thể là một ví dụ trong ngôn ngữ khác, nơi mọi thứ được thực hiện khác nhau dưới mui xe? Tôi chỉ không thấy làm thế nào "đặt tên" một đối tượng và "tham chiếu" một đối tượng là những thứ khác nhau. – slindsey3000

+0

Tôi cảm thấy như các thuật ngữ có thể hoán đổi cho nhau và "đặt tên" một đối tượng ngụ ý "tham chiếu" nó và "tham chiếu" một đối tượng ngụ ý bạn đã cho nó một "tên". – slindsey3000

+1

@ slindsey3000 Tôi thích thuật ngữ "tên" - vốn phổ biến hơn trong Python - chính vì nó * không * sử dụng "tham chiếu" hoặc bất kỳ biến thể nào của. "[Chuyển bởi] Tham chiếu [es]" là một tập hợp các từ quá tải. Nhưng có, thông tục họ được nhiều lần điều trị như nhau. Tuy nhiên, khi chỉ sử dụng "tên" và chỉ xác định mối quan hệ của nó với kết quả đánh giá của biến, tránh xung đột khi mở rộng phạm vi để nói về giá trị/biến trong nhiều ngôn ngữ khác. Để nói "int x = 1; // x reference 1" trong C++, sẽ rất sai. Khái niệm "đặt tên" là tổng quát hơn (và rìa). –

Các vấn đề liên quan