#!/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であるため、最初は機能しませんでした。そのため、属性から派生したものであっても、新しいインスタンスにはありません。StudentObject
selfただし、に渡すことができるs.idため、追加する必要があるのは、データ属性のアクセサーだけです。
ただし、attr_readeret 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
クラス定義の外でインスタンス変数(接頭辞「@」)を定義する必要がありますか?
また、名前にピリオドが含まれるメソッドを定義することはできません