Câu trả lời:
Viết @age
trực tiếp truy cập biến thể hiện @age
. Viết self.age
cho đối tượng tự gửi tin nhắn age
, thông thường sẽ trả về biến @age
thể hiện - nhưng có thể thực hiện bất kỳ số lượng nào khác tùy thuộc vào cách age
phương thức được thực hiện trong một lớp con nhất định. Ví dụ: bạn có thể có một lớp MiddleAgedSocialite luôn báo cáo tuổi của nó nhỏ hơn 10 tuổi so với thực tế. Hay thực tế hơn, một lớp PersistentPerson có thể đọc dữ liệu đó từ một cửa hàng liên tục, lưu trữ tất cả dữ liệu liên tục của nó trong một hàm băm.
Sự khác biệt là nó đang cách ly việc sử dụng phương thức này với việc thực hiện nó. Nếu việc triển khai tài sản là thay đổi - nói là giữ ngày sinh và sau đó tính tuổi dựa trên sự khác biệt về thời gian giữa bây giờ và ngày sinh - thì mã tùy thuộc vào phương pháp không cần thay đổi. Nếu nó sử dụng thuộc tính trực tiếp, thì sự thay đổi sẽ cần lan truyền đến các khu vực khác của mã. Theo nghĩa này, việc sử dụng thuộc tính trực tiếp dễ vỡ hơn so với sử dụng giao diện do lớp cung cấp cho nó.
Được cảnh báo khi bạn kế thừa một lớp từ Struct.new
đó là một cách gọn gàng để tạo một intializer ( Làm thế nào để tạo trình khởi tạo trong Ruby? )
class Node < Struct.new(:value)
def initialize(value)
@value = value
end
def show()
p @value
p self.value # or `p value`
end
end
n = Node.new(30)
n.show()
sẽ trở lại
30
nil
Tuy nhiên, khi bạn gỡ bỏ trình khởi tạo, nó sẽ trở lại
nil
30
Với định nghĩa lớp
class Node2
attr_accessor :value
def initialize(value)
@value = value
end
def show()
p @value
p self.value
end
end
Bạn nên cung cấp các nhà xây dựng.
n2 = Node2.new(30)
n2.show()
sẽ trở lại
30
30
Câu trả lời đầu tiên là hoàn toàn chính xác, nhưng với tư cách là một người mới tương đối, tôi không rõ ngay lập tức nó ngụ ý gì (gửi tin nhắn cho chính mình? Uh huh ...). Tôi nghĩ rằng một ví dụ ngắn sẽ giúp:
class CrazyAccessors
def bar=(val)
@bar = val - 20 # sets @bar to (input - 20)
end
def bar
@bar
end
def baz=(value)
self.bar = value # goes through `bar=` method, so @bar = (50 - 20)
end
def quux=(value)
@bar = value # sets @bar directly to 50
end
end
obj = CrazyAccessors.new
obj.baz = 50
obj.bar # => 30
obj.quux = 50
obj.bar # => 50
Không có sự khác biệt. Tôi nghi ngờ rằng nó đã được thực hiện chỉ vì giá trị tài liệu của việc nhìn thấy self.age
và other_person.age
gần nhau.
Tôi cho rằng việc sử dụng không cho phép một getter thực tế được viết trong tương lai, điều này có thể làm một cái gì đó phức tạp hơn là chỉ trả về một biến thể hiện và trong trường hợp đó phương thức sẽ không cần thay đổi.
Nhưng rốt cuộc, đó không phải là một sự trừu tượng khó có thể lo lắng, nếu việc triển khai đối tượng thay đổi, việc thay đổi các phương thức khác là hợp lý, đôi khi một tham chiếu đơn giản trong chính đối tượng là hoàn toàn hợp lý.
Trong mọi trường hợp, sự trừu tượng của age
tài sản vẫn không giải thích được việc sử dụng rõ ràng self
, vì chỉ đơn giản age
là cũng sẽ gọi người truy cập.
@age - chắc chắn là tuổi biến
self.age - đề cập đến tuổi tài sản thể hiện.