2009-10-15 33 views
35

Nếu tôi có lớp học này:Có cách nào để khởi tạo một đối tượng thông qua một băm?

class A 
    attr_accessor :b,:c,:d 
end 

và mã này:

a = A.new 
h = {"b"=>10,"c"=>20,"d"=>30} 

là nó có thể khởi tạo các đối tượng trực tiếp từ băm, mà không có tôi cần phải đi qua từng cặp và gọi instance_variable_set? Một cái gì đó như:

a = A.new(h) 

nên biến mỗi biến thể hiện thành biến có cùng tên trong mã băm.

Trả lời

50

Bạn có thể xác định một hàm khởi chạy trên lớp học của bạn:

class A 
    attr_accessor :b,:c,:d 
    def initialize(h) 
    h.each {|k,v| public_send("#{k}=",v)} 
    end 
end 

Hoặc bạn có thể tạo ra một mô-đun và sau đó "trộn nó trong"

module HashConstructed 
def initialize(h) 
    h.each {|k,v| public_send("#{k}=",v)} 
end 
end 

class Foo 
include HashConstructed 
attr_accessor :foo, :bar 
end 

Hoặc bạn có thể thử một cái gì đó giống như constructor

+3

+1. BTW, bạn có thể muốn xem xét sử dụng 'public_send' thay vì' send' để tránh gọi các nhà văn thuộc tính riêng :) – epidemian

+1

+1 cho đá quý constructor –

8

instance_variable_set được thiết kế cho loại trường hợp sử dụng này:

class A 
    def initialize(h) 
    h.each {|k,v| instance_variable_set("@#{k}",v)} 
    end 
end 

Đó là một phương pháp nào, vì vậy bạn cũng có thể gọi nó là sau khi xây dựng:

a = A.new({}) 
a.instance_variable_set(:@foo,1) 

Nhưng lưu ý cảnh báo ngụ ý trong documentation:

Thiết lập tên biến dụ bằng biểu tượng để đối tượng , do đó làm phiền những nỗ lực của tác giả của lớp để cố gắng cung cấp đóng gói thích hợp. Biến không cần phải tồn tại trước cuộc gọi này.

+1

Với tôi, việc kiểm tra để đảm bảo bạn chỉ có thể thiết lập những định nghĩa trong định nghĩa là khá quan trọng, làm cho đề xuất này không đáng tin cậy –

10

OpenStruct rất đáng xem xét:

require 'ostruct' # stdlib, no download 
the_hash = {"b"=>10, "c"=>20, "d"=>30} 
there_you_go = OpenStruct.new(the_hash) 
p there_you_go.C#=> 20 
+1

Đúng! Và bạn cũng có thể chuyển đổi JSON thành OpenStruct, điều này rất hay. 'JSON.parse ({a: 1, b: 2} .to_json, object_class: OpenStruct)' –

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