#!/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
6 に答える
まず、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
できます!
は最上位オブジェクトのインスタンス属性@data
であるため、最初は機能しませんでした。そのため、属性から派生したものであっても、新しいインスタンスにはありません。Student
Object
self
ただし、に渡すことができるs.id
ため、追加する必要があるのは、データ属性のアクセサーだけです。
ただし、attr_reader
et alはプライベートクラスメソッドであるため、直接使用することはできません。また、(プライベートであるため)「self.class.attr_reader
開いて実行する必要があります」と言うことはできませんObject
。これらの変更により、プログラムが変更されます。動作します...
@data = { :student => { :id => '123477'} }
class Student
end
s = Student.new
def s.id o
o.data[:student][:id]
#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!
end
class Object
attr_reader :data
end
puts s.id self
このコードは、いくつかの改善を加えて、独自の回答と同等の機能を果たします。(それを読んだだけで、あなたが達成しようとしていることがわかりました。)過度に複雑になるのを避けるために、メソッド名を動的に生成することは避けようとしました。
#!/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
あなたがそれを機能させたいと思ったようにコードを投稿したなら、あなたの質問はより明確になったと思います。編集を提案します。
#!/ 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'}} クラスの学生 def initialize(data) @data = data 終わり def get_id_override @data [:student] [:id] 終わり def get_first_name_override @data [:student] [:first_name] 終わり def get_last_name_override @data [:student] [:last_name] 終わり def get_email_override @data [:student] [:email] 終わり def get_telephone_override @data [:contact_info] [:telephone] 終わり def get_city_override @data [:contact_info] [:city] 終わり def get_state_override @data [:contact_info] [:state] 終わり def get_zip_code_override @data [:contact_info] [:zip_code] 終わり def get_social_security_number_override @data [:contact_info] [:social_security_number] 終わり 終わり s = Student.new(@data) def s.id get_id_override 終わり def s.first_name get_first_name_override 終わり def s.last_name get_last_name_override 終わり def s.email get_email_override 終わり def s.contact_info get_telephone_override 終わり def s.city get_city_override 終わり def s.state get_state_override 終わり def s.zipcode get_zip_code_override 終わり def s.ssn get_social_security_number_override 終わり s.idを置きます s.first_nameを置きます s.last_nameを置きます s.emailを置きます s.contact_infoを置きます s.cityを置きます s.stateを置きます s.zipcodeを置きます s.ssnを置きます
これがいくつかの作業の後の答えです。誰もが私に知らせてくれるよりも良い答えを持っています。
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
クラス定義の外でインスタンス変数(接頭辞「@」)を定義する必要がありますか?
また、名前にピリオドが含まれるメソッドを定義することはできません