루비에서는 인스턴스 외부의 속성 (인스턴스 변수)에 액세스 할 수 없다는 것을 상기하십시오. 인스턴스의 public 메소드에만 액세스 할 수 있습니다.
는
당신은 당신이 설명하는대로 속성 역할을하는 클래스의 방법을 만들 attr_accessor
를 사용할 수 있습니다
irb(main):001:0> class Array
irb(main):002:1> attr_accessor :_meta_
irb(main):003:1> end
=> nil
irb(main):004:0>
irb(main):005:0* x = [1,2,3]
=> [1, 2, 3]
irb(main):006:0> x._meta_ = Hash.new
=> {}
irb(main):007:0> x._meta_[:key] = 'value'
=> "value"
irb(main):008:0>
를 접근에 대한 기본 초기화를 할 수있는 간단한 방법을 위해, 우리는 기본적으로해야합니다 reimplement attr_accessor
ourselves :
class Class
def attr_accessor_with_default accessor, default_value
define_method(accessor) do
name = "@#{accessor}"
instance_variable_set(name, default_value) unless instance_variable_defined?(name)
instance_variable_get(name)
end
define_method("#{accessor}=") do |val|
instance_variable_set("@#{accessor}", val)
end
end
end
class Array
attr_accessor_with_default :_meta_, {}
end
x = [1,2,3]
x._meta_[:key] = 'value'
p x._meta_
y = [4,5,6]
y._meta_[:foo] = 'bar'
p y._meta_
기다려라! 출력이 올바르지 않습니다.
{:key=>"value"}
{:foo=>"bar", :key=>"value"}
리터럴 해시의 기본값을 기준으로 클로저를 만들었습니다. 같은 문자 해시 때마다 재사용에 반대 Hash.new
가 기본 값이 검색 될 때마다 호출되기 때문에
class Class
def attr_accessor_with_default accessor, &default_value_block
define_method(accessor) do
name = "@#{accessor}"
instance_variable_set(name, default_value_block.call) unless instance_variable_defined?(name)
instance_variable_get(name)
end
define_method("#{accessor}=") do |val|
instance_variable_set("@#{accessor}", val)
end
end
end
class Array
attr_accessor_with_default :_meta_ do Hash.new end
end
x = [1,2,3]
x._meta_[:key] = 'value'
p x._meta_
y = [4,5,6]
y._meta_[:foo] = 'bar'
p y._meta_
이제 출력이 올바른지 :
더 좋은 방법은 단순히 블록을 사용할 수 있습니다.
{:key=>"value"}
{:foo=>"bar"}
단순히 Array에서 상속받은 클래스를 만들고 원하는 기능을 추가 할 수없는 이유가 있습니까? –
이것이 바람직한 방법이지만,이 질문은 테스트 목적으로 만 실험 코드와 관련이 있습니다 ... 질문을 업데이트 할 것입니다. – dreftymac
이미 내 답변을 수락 했음에도 추가 한 속성의 기본값을 설정하는 방법에 대한 설명이 추가되었습니다 (질문 업데이트 당). –