2012-10-16 34 views
23

Tôi mới bắt đầu học ruby ​​và tôi không thấy sự khác biệt giữa một số @instace_variable và thuộc tính được khai báo sử dụng attr_accessor.Sự khác biệt giữa @instance_variable và attr_accessor

sự khác biệt giữa hai loại sau đây là gì:

class MyClass 
    @variable1 
end 

class MyClass 
    attr_accessor :variable1 
end 

tôi đã tìm kiếm rất nhiều hướng dẫn trực tuyến và tất cả mọi người sử dụng ký hiệu khác nhau, Liệu nó có làm bất cứ điều gì với ruby phiên bản? Tôi cũng đã tìm kiếm vài chủ đề cũ trong StackOverflow

What is attr_accessor in Ruby?
What's the Difference Between These Two Ruby Class Initialization Definitions?

Nhưng tôi vẫn không thể tìm ra cách tốt nhất để sử dụng là gì.

+3

'attr_accessor' sẽ tạo một biến mẫu, phương thức _plus_ để đọc và viết biến mẫu. –

+4

Thực ra, @AlexWayne, 'attr_accessor' chỉ khai báo các phương thức. Các biến cá thể không phải được khai báo; chúng sẽ trở thành hiện hữu khi bạn cố truy cập chúng (và giá trị của chúng là 'nil' nếu truy cập đầu tiên đó là đọc thay vì viết). –

Trả lời

45

Biến thể hiện không hiển thị bên ngoài đối tượng mà nó đang ở; nhưng khi bạn tạo một attr_accessor, nó tạo ra một biến cá thể và cũng làm cho nó có thể nhìn thấy được (và có thể chỉnh sửa được) bên ngoài đối tượng.

Ví dụ với biến Ví dụ (không attr_accessor)

class MyClass 
    def initialize 
    @greeting = "hello" 
    end 
end 

m = MyClass.new 
m.greeting #results in the following error: 
    #NoMethodError: undefined method `greeting' for #<MyClass:0x007f9e5109c058 @greeting="hello"> 

Ví dụ sử dụng attr_accessor:

class MyClass 
    attr_accessor :greeting 

    def initialize 
    @greeting = "hello" 
    end 
end 

m2 = MyClass.new 
m2.greeting = "bonjour" # <-- set the @greeting variable from outside the object 
m2.greeting #=> "bonjour" <-- didn't blow up as attr_accessor makes the variable accessible from outside the object 

Hope mà làm cho nó rõ ràng.

+3

thực tế tôi là từ java background và java instance variable có thể được hiển thị bên ngoài bằng cách sử dụng các modifier truy cập (public, protected), đó là lý do tại sao tôi không thể hiểu tại sao các biến instance trong ruby ​​không thể được truy cập từ bên ngoài. Cảm ơn bạn đã giải thích, chúc mừng! –

+1

m2.greeting ở cuối biến thành "hello" – dtc

+0

Nat - @greeting = "hello" nên được thay đổi thành greeting = "hello" vì như bạn đã nói, attr_accessor đã tạo biến mẫu và hàm truy cập. Không cần sử dụng biểu tượng @. –

7

attr_accesor cung cấp cho bạn các phương pháp để đọc và ghi các biến mẫu. Các biến mẫu được thiết kế để ẩn từ thế giới bên ngoài để giao tiếp với chúng, chúng ta cần có các phương thức attr _ibute accesor.

25

Biến thể hiện không hiển thị bên ngoài lớp học.

class MyClass 
    def initialize 
    @message = "Hello" 
    end 
end 

msg = MyClass.new 
@message 
#==> nil # This @message belongs to the global object, not msg 
msg.message 
#==> NoMethodError: undefined method `message' 
[email protected] 
#==> SyntaxError: syntax error, unexpected tIVAR 

Bây giờ, bạn luôn có thể làm điều này:

msg.instance_eval { @message } 

Nhưng đó là vụng về và cheatish. Poking quanh lớp của người khác có thể là giáo dục, nhưng mã khách hàng của bạn không nên làm điều đó nếu bạn muốn nhận được kết quả đáng tin cậy. Mặt khác, nếu bạn muốn khách hàng có thể xem các giá trị đó, đừng làm cho họ sử dụng instance_eval; thay vào đó, xác định một phương pháp mà hiện các trick:

class MyClass 
    def message 
    return @message 
    end 
end 
msg.message 
# ==> "Hello" 

Bởi vì bạn thường xuyên muốn làm điều đó, Ruby cung cấp một phím tắt để làm cho nó dễ dàng hơn. Mã bên dưới có kết quả chính xác giống như mã ở trên:

class MyClass 
    attr_reader :message 
end 

Đó không phải là một loại biến mới; nó chỉ là một cách viết tắt để xác định phương pháp. Bạn có thể xem msg.methods và thấy rằng nó hiện có phương thức message.

Bây giờ, điều gì xảy ra nếu bạn muốn cho phép người ngoài không chỉ thấy giá trị của một biến mẫu, mà còn thay đổi giá trị đó? Cho rằng, bạn phải xác định một phương pháp khác để chuyển nhượng, với một = trong tên:

class MyClass 
    def message=(new_value) 
    @message = new_value 
    end 
end 
msg.message = "Good-bye" 
msg.message 
# ==> "Good-bye" 

Lưu ý rằng toán tử gán là bán huyền diệu ở đây; mặc dù có khoảng cách giữa msg.message=, Ruby vẫn biết gọi phương thức message=. Các toán tử kết hợp như += và như vậy sẽ kích hoạt các cuộc gọi đến phương thức.

lần nữa, đây là một thiết kế thông thường, vì vậy của Ruby cung cấp một phím tắt cho nó, quá:

class MyClass 
    attr_writer :message 
end 

Bây giờ, nếu bạn sử dụng attr_writer bởi chính nó, bạn sẽ có được một thuộc tính có thể được sửa đổi, nhưng chưa từng thấy . Có một số trường hợp sử dụng lẻ mà đó là những gì bạn muốn, nhưng hầu hết thời gian, nếu bạn định cho phép người ngoài sửa đổi biến, bạn cũng muốn họ có thể đọc nó. Thay vì phải khai báo cả một attr_reader và một attr_writer, bạn có thể tuyên bố cả hai cùng một lúc như vậy:

class MyClass 
    attr_accessor :message 
end 

Một lần nữa, đây chỉ là một shortcut để xác định phương pháp cho phép bạn có được ở các instance variable từ bên ngoài lớp học.

+4

đây là một câu trả lời tốt hơn và tiết kiệm hơn, trả lời câu hỏi rõ ràng cho những người đến từ các ngôn ngữ khác - cảm ơn! – manroe

1

attr_accessor định nghĩa các phương thức, bạn có thể gọi chúng từ bên ngoài lớp học. Bạn chỉ có thể truy cập @variable từ bên trong lớp học.

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