2009-07-28 41 views

Trả lời

28

Thuộc tính là tài sản cụ thể của một đối tượng. Phương thức là khả năng của một đối tượng.

Trong Ruby tất cả các biến mẫu (thuộc tính) là riêng tư theo mặc định. Nó có nghĩa là bạn không có quyền truy cập vào chúng bên ngoài phạm vi của bản thân cá thể. Cách duy nhất để truy cập thuộc tính là sử dụng phương thức truy cập.

class Foo 
    def initialize(color) 
    @color = color 
    end 
end 

class Bar 
    def initialize(color) 
    @color = color 
    end 

    def color 
    @color 
    end 
end 

class Baz 
    def initialize(color) 
    @color = color 
    end 

    def color 
    @color 
    end 

    def color=(value) 
    @color = value 
    end 
end 

f = Foo.new("red") 
f.color # NoMethodError: undefined method ‘color’ 

b = Bar.new("red") 
b.color # => "red" 
b.color = "yellow" # NoMethodError: undefined method `color=' 

z = Baz.new("red") 
z.color # => "red" 
z.color = "yellow" 
z.color # => "yellow" 

Bởi vì đây là một hành vi thực sự commmon, Ruby cung cấp một số phương pháp thuận tiện để xác định phương pháp accessor: attr_accessor, attr_writerattr_reader.

+1

Bạn luôn có thể truy cập biến bằng cách sử dụng Object.instance_variable_get (: @ symbol), để tránh sự cần thiết phải xác định người truy cập. –

+6

Đây không phải là thực tế tốt. ;) instance_variable_get nên được dành riêng cho các công cụ lập trình meta. Nó giống như việc định nghĩa một phương thức riêng tư, sau đó truy cập nó bằng phương thức send (: method). –

38

Thuộc tính chỉ là một phím tắt. Nếu bạn sử dụng attr_accessor để tạo một thuộc tính, Ruby chỉ khai báo một biến cá thể và tạo ra các phương thức getter và setter cho bạn.

Kể từ khi bạn yêu cầu một ví dụ:

class Thing 
    attr_accessor :my_property 

    attr_reader :my_readable_property 

    attr_writer :my_writable_property 

    def do_stuff 
     # does stuff 
    end 
end 

Đây là cách bạn muốn sử dụng lớp:

# Instantiate 
thing = Thing.new 

# Call the method do_stuff 
thing.do_stuff 

# You can read or write my_property 
thing.my_property = "Whatever" 
puts thing.my_property 

# We only have a readable accessor for my_readable_property 
puts thing.my_readable_property 

# And my_writable_propety has only the writable accessor 
thing.my_writable_property = "Whatever" 
+3

Tôi nghĩ đây là câu trả lời tốt hơn nhiều so với câu trả lời được chấp thuận ... –

4

Thuộc tính, nói đúng, các biến mẫu của cá thể lớp. Nói chung, các thuộc tính thường được khai báo bằng cách sử dụng các phương thức kiểu attr_X, trong khi các phương thức được khai báo đơn giản như là.

Một ví dụ đơn giản có thể là:

attr_accessor :name 
attr_reader :access_level 

# Method 
def truncate_name! 
    @name = truncated_name 
end 

# Accessor-like method 
def truncated_name 
    @name and @name[0,14] 
end 

# Mutator-like method 
def access_level=(value) 
    @access_level = value && value.to_sym 
end 

Sự khác biệt giữa hai số này là hơi độc đoán trong Ruby vì không tiếp cận trực tiếp với họ được quy định cụ thể. Điều này tương phản mạnh mẽ với các ngôn ngữ khác như C, hoặc C++ và Java, nơi truy cập của một thuộc tính đối tượng và các phương thức gọi được thực hiện thông qua hai cơ chế khác nhau. Java nói riêng có các phương thức accessor/mutator được viết ra như vậy, trong khi Ruby được ngụ ý theo tên. Thường là trường hợp, như trong ví dụ, nơi sự khác biệt giữa "accessor thuộc tính" và phương thức tiện ích cung cấp dữ liệu dựa trên giá trị của thuộc tính, chẳng hạn như truncated_name, là nhỏ.

1
class MyClass 
    attr_accessor :point 

    def circle 
    return @circle 
    end 

    def circle=(c) 
    @circle = c 
    end 
end 

Thuộc tính là thuộc tính của đối tượng. Trong trường hợp này, tôi sử dụng phương thức lớp attr_accessor để định nghĩa thuộc tính: point cùng với một phương thức getter và setter ngầm định cho điểm.

obj = MyClass.new 
obj.point = 3 
puts obj.point 
> 3 

Phương thức 'vòng tròn' là một hàm được xác định rõ ràng cho biến thể @circle. 'circle =' là một setter được xác định rõ ràng cho biến cá thể @circle.

0

Tôi đã nghe từ "thuộc tính" tham chiếu, trong các vòng kết nối đặc trưng của Ruby, với bất kỳ phương thức nào không lấy đối số.

class Batman 

    def favorite_ice_cream 
    [ 
     'neopolitan', 
     'chunky monkey', 
     'chocolate', 
     'chocolate chip cookie dough', 
     'whiskey' 
    ].shuffle[0]   
    end 

end 

Ở trên, my_newest_batman.favorite_ice_cream sẽ là một thuộc tính.

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