2012-02-03 18 views
5

Với chuỗi người ta có thể làm điều này:cách Generic để thay thế một đối tượng trong phương pháp riêng của nó

a = "hello" 
a.upcase! 
p a #=> "HELLO" 

Nhưng làm thế nào tôi sẽ viết phương pháp riêng của tôi như vậy?

Giống như (mặc dù điều đó không làm việc rõ ràng):

class MyClass 
    def positify! 
    self = [0, self].max 
    end 
end 

Tôi biết có một số thủ thuật có thể sử dụng trên dây nhưng những gì nếu tôi đang cố gắng để làm một cái gì đó như thế này cho đối tượng?

Trả lời

4

Vâng, phương pháp upcase! không thay đổi nhận dạng đối tượng, nó chỉ thay đổi cấu trúc bên trong của nó (s.object_id == s.upcase!.object_id).

Mặt khác, các số là các đối tượng bất biến và do đó, bạn không thể thay đổi giá trị của chúng mà không thay đổi nhận dạng của chúng. AFAIK, không có cách nào để một đối tượng tự thay đổi nhận dạng của nó, nhưng, tất nhiên, bạn có thể thực hiện phương thức positify! thay đổi các thuộc tính của đối tượng của nó - và này sẽ là một điểm tương tự của những gì upcase! làm cho chuỗi.

2

Chuyển nhượng hoặc ràng buộc biến cục bộ (sử dụng toán tử =) được tích hợp sẵn với ngôn ngữ chính và không có cách nào để ghi đè hoặc tùy chỉnh nó. Bạn có thể chạy một bộ tiền xử lý trên mã Ruby của bạn, nó sẽ chuyển đổi cú pháp tùy chỉnh của riêng bạn thành Ruby hợp lệ. Bạn cũng có thể chuyển một số Binding vào phương thức tùy chỉnh, có thể xác định lại các biến động. Điều này sẽ không đạt được hiệu quả mà bạn đang tìm kiếm, mặc dù.

Hiểu rằng self = không bao giờ có thể hoạt động, bởi vì khi bạn nói a = "string"; a = "another string" bạn không sửa đổi bất kỳ đối tượng nào; bạn đang rebinding biến cục bộ thành một đối tượng khác. Bên trong phương thức tùy chỉnh của bạn, bạn đang ở một phạm vi khác và bất kỳ biến địa phương nào bạn ràng buộc sẽ chỉ tồn tại trong phạm vi đó; nó sẽ không ảnh hưởng đến phạm vi mà bạn gọi là phương thức.

2

Bạn không thể tự thay đổi để trỏ đến bất kỳ mục nào khác ngoài đối tượng hiện tại của nó. Bạn có thể thay đổi các biến mẫu, chẳng hạn như trong chuỗi trường hợp đang thay đổi các ký tự cơ bản thành chữ hoa.

Như đã chỉ ra trong câu trả lời này: Ruby and modifying self for a Float instance

Có một trick đề cập ở đây đó là một công trình xung quanh, mà là để viết cho em lớp như là một wrapper xung quanh đối tượng khác. Sau đó, lớp wrapper của bạn có thể thay thế đối tượng được bao bọc theo ý muốn. Tôi do dự khi nói rằng đây là một ý tưởng hay.

7

Nhiều lớp không thay đổi (ví dụ: Numeric, Symbol, ...), vì vậy không có phương pháp nào cho phép bạn thay đổi giá trị của chúng.

Mặt khác, bất kỳ Object nào cũng có thể có biến mẫu và các biến này có thể được sửa đổi.

Có một cách dễ dàng để ủy quyền hành vi cho một đối tượng đã biết (nói 42) và có thể thay đổi, sau này, sang một đối tượng khác, sử dụng SimpleDelegator.Trong ví dụ dưới đây, quacks_like_an_int hoạt động như một Integer:

require 'delegate' 
quacks_like_an_int = SimpleDelegator.new(42) 
quacks_like_an_int.round(-1) # => 40 
quacks_like_an_int.__setobj__(666) 
quacks_like_an_int.round(-1) # => 670 

Bạn có thể sử dụng nó để thiết kế một lớp quá, ví dụ:

require 'delegate' 
class MutableInteger < SimpleDelegator 
    def plus_plus! 
    __setobj__(self + 1) 
    self 
    end 

    def positify! 
    __setobj__(0) if self < 0 
    self 
    end 
end 

i = MutableInteger.new(-42) 
i.plus_plus! # => -41 
i.positify! # => 0 
Các vấn đề liên quan