2008-10-08 41 views
5

Tôi có một đối tượng mà tôi đang chuyển trong một cuộc gọi phương thức. Giả sử tôi đang sử dụng ngôn ngữ chỉ cho phép bạn chuyển đối tượng theo tham chiếu, như Java hoặc PHP. Nếu phương thức thực hiện thay đổi đối tượng, nó sẽ ảnh hưởng đến người gọi. Tôi không muốn điều này xảy ra. Vì vậy, có vẻ như tôi cần tạo một bản sao của đối tượng.Chuyển bản sao của đối tượng sang phương thức - người thực hiện sao chép?

Câu hỏi của tôi là: ai có trách nhiệm sao chép đối tượng? Người gọi, trước khi nó gọi phương thức? Hoặc callee, trước khi nó thay đổi đối tượng?

EDIT: Chỉ cần làm rõ, tôi muốn điều này là một phần của hợp đồng của phương pháp này - rằng nó không bao giờ sửa đổi đối tượng ban đầu. Vì vậy, có vẻ như nó nên được lên đến phương pháp để làm cho bản sao. Nhưng sau đó người gọi không có bảo vệ từ một phương pháp mà không làm điều này đúng cách. Tôi đoán điều đó có thể chấp nhận được - chỉ có một lựa chọn thay thế khác có vẻ là có được điều này được xây dựng trong ngôn ngữ.

+0

Tôi không hiểu điều này. Bạn có một phương thức thay đổi đối tượng, nhưng hợp đồng ngụ ý của phương thức là nó không có. Bạn có thể làm rõ thêm điều này không? –

+0

Phương pháp này không được phép ảnh hưởng đến đối tượng của người gọi, nhưng nó có thể thay đổi bản sao của đối tượng. –

Trả lời

0

Tùy thuộc, có bất kỳ lý do nào mà phương pháp có thể được gọi trong tương lai mà bạn muốn người gọi nhìn thấy thay đổi không? Nếu vậy thì người gọi nên tạo bản sao. Nếu không, các callee nên làm cho nó. Tôi sẽ nói rằng trường hợp thứ hai có lẽ là phổ biến hơn.

5

Nói chung, người gọi sẽ tạo bản sao nếu có lo ngại về các thay đổi. Nếu người gọi không quan tâm, phương pháp nên tạo bản sao nếu cần phải làm điều gì đó mà nó biết không nên tồn tại.

0

Nếu bạn có người gọi nhân bản đối tượng, nó cho bạn sự linh hoạt để không sử dụng một bản sao (không nhân bản nó trước), và cũng có nghĩa là bạn không phải trả lại một đối tượng mới, bạn chỉ có thể hoạt động tài liệu tham khảo được thông qua.

0

Phản ứng đầu tiên của tôi là trách nhiệm của người gọi, nhưng tôi nghĩ nó thực sự phụ thuộc.

Tùy thuộc vào hợp đồng được xác định giữa hai phương pháp. Phương pháp đang thực hiện thay đổi phải xác định rõ ràng thực tế đó và để người gọi đưa ra quyết định. HOẶC, Phương pháp đang thực hiện các thay đổi phải xác định rõ ràng rằng nó sẽ KHÔNG thực hiện bất kỳ thay đổi nào đối với đối tượng được truyền và sau đó nó sẽ chịu trách nhiệm tạo bản sao.

1

Người gọi. Bởi vì, đôi khi bạn muốn thực hiện thay đổi đối với bản thân đối tượng và các lần khác vào một bản sao.

Mặc dù, tôi coi đó là một thực hành tồi để callee sửa đổi các đối tượng được truyền (ít nhất là trong các ngôn ngữ hướng đối tượng). Điều này có thể gây ra nhiều tác dụng phụ không mong muốn.

(sau khi bạn) EDIT: Trong trường hợp đó nó là trách nhiệm callee của để thực thi các hợp đồng, vì vậy có hai tùy chọn:

  • Các callee chỉ đơn giản là không sửa đổi các đối tượng
  • hoặc callee sao chép đối tượng và làm việc với các bản sao sau đó
+0

Điều này nghe có vẻ đúng, đó là hợp đồng của callee, và do đó đó là trách nhiệm. Nhưng sau đó chúng ta không cho nó quá nhiều sức mạnh, và không gói gọn nó? Bây giờ nó có thể làm thiệt hại bên ngoài của chính nó. –

+0

Nếu nó hoàn thành hợp đồng bằng cách đảm bảo không có vật thể nào được chuyển đổi thì không có tác dụng phụ và không có thiệt hại nào được thực hiện. –

1

Vì vậy, bạn muốn làm một cái gì đó giống như

MyObject m = new MyObject(); MyObject n = MyObjectProcessor.process (m) ;?

Có vẻ như đơn giản hơn đối với tôi để làm điều gì đó như MyObject n = MyObjectProcessor.alter (m.clone());

nơi rõ ràng ai đang làm gì cho ai. Bạn có thể làm cho đối số rằng hàm lớp bộ xử lý không có tác dụng phụ, tức là nó sẽ trả về một đối tượng mới bất kỳ lúc nào nó sẽ thay đổi trạng thái, nhưng (AFAIK) không được tuân thủ một cách nhất quán trong OO như trái ngược với lập trình hàm.

Điều gì đó như trên có thể vô hại, miễn là nó được đặt tên rõ ràng và được ghi lại.

1

Chúng tôi có thể xem xét ruby ​​để được hướng dẫn. Họ sử dụng một! biểu tượng để chỉ ra rằng một đối tượng được sửa đổi tại chỗ. Vì vậy, salary.add (10000) trả về một đối tượng mới nhưng salary.add! (10000) trả về đối tượng ban đầu nhưng được sửa đổi. Bạn có thể sử dụng cùng một ý tưởng trong Java hoặc PHP bằng cách sử dụng một quy ước đặt tên cục bộ.

0

Tôi sẽ nói callee: nó đơn giản hóa các cuộc gọi và người gọi sẽ không phải lo lắng về tính toàn vẹn của các đối tượng đã cho. Đó là trách nhiệm của các callee để bảo toàn tính toàn vẹn.

0

Tôi cho rằng bạn sẽ có thứ gì đó như khai báo const. Đây sẽ là trình biên dịch được thi hành và sẽ hiệu quả hơn việc tạo các bản sao của các đối tượng của bạn.

0

Tôi nghĩ người gọi nên tạo bản sao, chỉ để làm cho việc đặt tên dễ dàng hơn. Bạn có thể đặt tên cho phương thức của mình là Foo() thay vì CloneBarAndFooClone().

Hãy so sánh:

void RemoveZeroDollarPayments(Order order) 

vs

Order CloneOrderAndRemoveZeroDollarPaymentsFromClone(Order order) 
0

Nếu không thay đổi đối tượng là một phần của hợp đồng phương pháp, khả năng duy nhất là sau khi các bản sao thực hiện bên trong phương pháp này. Nếu không, bạn đang nói dối với khách hàng của bạn.

Thực tế là bạn thực sự cần phải sửa đổi một đối tượng chính xác như đối tượng được trao cho bạn chỉ là chi tiết triển khai không nên đặt gánh nặng lên người gọi. Trong thực tế, anh ta thậm chí không cần phải có khả năng hiển thị về điều đó.

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