#!/usr/bin/env ruby
# this is the data I have
@data = {
:student => {
:id => '123477',
:first_name => 'Lazlo',
:last_name =>'Fortunatus',
:email=>'Lazlo@fortunatus.org'
},
:contact_info => {
:telephone=>'1 415 222-2222',
:address => '123 Main St',
:city =>'Beverly Hills',
:state=>'California',
:zip_code=>90210,
:social_security_number =>'111-11-1111'
}
}
class Student
# not fully implemented - this is what I need help on.
def get_id_original
# I need this to return the value @data[:student][:id]
end
def get_city_original
# I need this to return the value @data[:contact_info][:city]
end
end
s = Student.new
# this is the original method
# how can I access the @data variable here I tried @data[:student][:id] doesnt work
# I realize that data is outside of the scope of this method. However, is there any way!
s.get_id_original
# My goal is to have a singleton method that acts exactly like get_id_original,
# but get_id_original doesn't work.
def s.id
get_id_original
end
答案 0 :(得分:1)
首先,你的id
方法实际上必须进入课堂。
您可以尝试这样的事情:
@data = { :student => { :id => '123477'} }
class Student
attr_accessor :id
def initialize(student)
self.id = student[:id]
end
end
s = Student.new(@data[:student])
puts s.id
答案 1 :(得分:1)
它最初没有工作,因为@data
是顶级对象的实例属性,所以即使Student
派生自Object
,属性不在新实例中。
但您可以将self
传递给s.id
,因此您需要添加的唯一内容是数据属性的访问者。
然而,这有点棘手,因为attr_reader
等人是私有类方法所以你不能直接使用它们,而你不能(因为它是私有的)只是说{{ 1}},您必须打开self.class.attr_reader
并执行此操作...通过这些更改,您的程序可以正常工作......
Object
答案 2 :(得分:0)
#!/usr/bin/ruby @data = { :student => { :id => '123477', :first_name => 'Lazlo', :last_name =>'Fortunatus', :email=>'Lazlo@fortunatus.org' }, :contact_info => { :telephone=>'1 415 222-2222', :address => '123 Main St', :city =>'Beverly Hills', :state=>'California', :zip_code=>90210, :social_security_number =>'111-11-1111' } } class Student def initialize( data ) @data = data end def get_id_override @data[:student][:id] end def get_first_name_override @data[:student][:first_name] end def get_last_name_override @data[:student][:last_name] end def get_email_override @data[:student][:email] end def get_telephone_override @data[:contact_info][:telephone] end def get_city_override @data[:contact_info][:city] end def get_state_override @data[:contact_info][:state] end def get_zip_code_override @data[:contact_info][:zip_code] end def get_social_security_number_override @data[:contact_info][:social_security_number] end end s = Student.new(@data) def s.id get_id_override end def s.first_name get_first_name_override end def s.last_name get_last_name_override end def s.email get_email_override end def s.contact_info get_telephone_override end def s.city get_city_override end def s.state get_state_override end def s.zipcode get_zip_code_override end def s.ssn get_social_security_number_override end puts s.id puts s.first_name puts s.last_name puts s.email puts s.contact_info puts s.city puts s.state puts s.zipcode puts s.ssn
以下是一些工作后的答案。任何人都有比我更好的答案让我知道。
答案 3 :(得分:0)
你真的应该传递数据对象,以便它s
有自己的引用。
@data = { :student => { :id => '123477'} }
class Student
attr_accessor :data
def initialize(data)
@data = data
end
end
s = Student.new(@data)
# or you can use s.data = @data
def s.id
@data[:student][:id]
end
puts s.id
谨慎一点。对最外层范围内@data
的任何修改都将反映在s
中,因为两个@data
变量都指向内存中的同一对象。
但是如果你不想修改Student课程怎么办?您只需将访问者添加到s
:
@data = { :student => { :id => '123477'} }
class Student
end
s = Student.new
class << s
attr_accessor :data
end
def s.id
@data[:student][:id]
end
s.data = @data
puts s.id
答案 4 :(得分:0)
此代码与您自己的答案相同,但有一些改进。 (只有阅读,我才意识到你要完成的任务。)为了避免过于复杂,我试图避免动态生成方法名称。
#!/usr/bin/env ruby
require 'forwardable'
@data = {
:student => {
:id => '123477',
:first_name => 'Lazlo',
:last_name =>'Fortunatus',
:email=>'Lazlo@fortunatus.org'
},
:contact_info => {
:telephone=>'1 415 222-2222',
:address => '123 Main St',
:city =>'Beverly Hills',
:state=>'California',
:zip_code=>90210,
:social_security_number =>'111-11-1111'
}
}
class ContactInfo
def initialize( data )
@data = data
end
def get_telephone_override
@data[:telephone]
end
def get_city_override
@data[:city]
end
def get_state_override
@data[:state]
end
def get_zip_code_override
@data[:zip_code]
end
def get_social_security_number_override
@data[:social_security_number]
end
end
class Student
extend Forwardable # enables delegation (see ruby-doc.org's standard library)
# delegates multiple methods to @contact_info, so they can be called on Student.
# Remember to have the leading colon.
def_delegators :@contact_info,
:get_telephone_override,
:get_city_override,
:get_state_override,
:get_zip_code_override,
:get_social_security_number_override
def initialize( data )
@data = data[:student]
# this is an example of composing objects to achieve separation of concerns.
# we use delegators so ContactInfo methods are available on the Student instance.
@contact_info = ContactInfo.new(data[:contact_info])
end
def get_id_override
@data[:id]
end
def get_first_name_override
@data[:first_name]
end
def get_last_name_override
@data[:last_name]
end
def get_email_override
@data[:email]
end
end
s = Student.new(@data)
class << s
alias_method :id, :get_id_override
alias_method :first_name, :get_first_name_override
alias_method :last_name, :get_last_name_override
alias_method :email, :get_email_override
alias_method :contact_info, :get_telephone_override
alias_method :city, :get_city_override
alias_method :state, :get_state_override
alias_method :zipcode, :get_zip_code_override
alias_method :ssn, :get_social_security_number_override
end
puts s.id
puts s.first_name
puts s.last_name
puts s.email
puts s.contact_info
puts s.city
puts s.state
puts s.zipcode
puts s.ssn
我认为,如果你发布了代码,那么你的问题会更加清晰。我打算建议编辑。
答案 5 :(得分:-2)
您是否应该在类定义之外定义实例变量(以“@”为前缀)?
此外,您无法定义名称为
的句点的方法