红宝石初始化对象
回答
您正在指示的代码将参数传递给initialize
函数。你肯定会必须要么使用initialize
,或使用更无聊的语法:
test = Test.new
test.name = 'Some test object'
正如其他人所提到的,要做到这一点最简单的方法是定义一个initialize
方法。如果你不想这样做,你可以让你的课程继承Struct。
class Test < Struct.new(:name)
end
所以现在:
>> t = Test.new("Some Test Object")
=> #<struct Test name="Some Test Object">
>> t.name
=> "Some Test Object"
OK,
我想出了一个解决方案。它使用初始化方法,但另一方面完全按照你想要的。
class Test
attr_accessor :name
def initialize(init)
init.each_pair do |key, val|
instance_variable_set('@' + key.to_s, val)
end
end
def display
puts @name
end
end
t = Test.new :name => 'hello'
t.display
高兴吗? :)
使用继承的替代解决方案。请注意,使用此解决方案,您不需要显式声明attr_accessor!
class CSharpStyle
def initialize(init)
init.each_pair do |key, val|
instance_variable_set('@' + key.to_s, val)
instance_eval "class << self; attr_accessor :#{key.to_s}; end"
end
end
end
class Test < CSharpStyle
def initialize(arg1, arg2, *init)
super(init.last)
end
end
t = Test.new 'a val 1', 'a val 2', {:left => 'gauche', :right => 'droite'}
puts "#{t.left} <=> #{t.right}"
有一种通用的方法来完成复杂的对象初始化 - 通过必要的动作传递块。该块可在该对象的上下文进行评估,所以你可以很方便地访问所有的实例变量,方法等
继续你的榜样
class Test
attr_accessor :name
def initialize(&block)
instance_eval(&block)
end
end
然后
t = Test.new { @name = 'name' }
或
t = Test.new do
self.name = 'name'
# other initialization, if needed
end
请注意,这种方式并不需要复杂的initialize
方法(实际上是单线)。
会需要继承测试(在这里与自己的方法和初始化所示)例如为:
class Test
attr_accessor :name, :some_var
def initialize some_var
@some_var = some_var
end
def some_function
"#{some_var} calculation by #{name}"
end
end
class SubClassedTest < Test
def initialize some_var, attrbs
attrbs.each_pair do |k,v|
instance_variable_set('@' + k.to_s, v)
end
super(some_var)
end
end
tester = SubClassedTest.new "some", name: "james"
puts tester.some_function
输出:some calculation by james
你能做到这一点。
class Test
def not_called_initialize(but_act_like_one)
but_act_like_one.each_pair do |variable,value|
instance_variable_set('@' + variable.to_s, value)
class << self
self
end.class_eval do
attr_accessor variable
end
end
end
end
(t = Test.new).not_called_initialize :name => "Ashish", :age => 33
puts t.name #=> Ashish
puts t.age #=> 33
一个优点是,你甚至不必使用attr_accessor
来定义实例变量的前期。您可以通过not_called_initialize
方法传递所需的所有实例变量,并让它创建它们,除了定义getter和setter。
如果您不想覆盖initialize
,那么您必须向上移动并覆盖new
。这里有一个例子:
class Foo
attr_accessor :bar, :baz
def self.new(*args, &block)
allocate.tap do |instance|
if args.last.is_a?(Hash)
args.last.each_pair do |k,v|
instance.send "#{k}=", v
end
else
instance.send :initialize, *args
end
end
end
def initialize(*args)
puts "initialize called with #{args}"
end
end
如果您传递的最后一件事是一个Hash它会绕过initialize
,并立即拨打制定者。如果你传递了其他的东西,它会调用这些参数初始化。
如前所述,明智的做法是使用Struct
或定义Test#initialize
方法。这正是结构和构造函数的用途。使用对应属性的选项哈希是你的C#示例的最接近的,这是一个正常的前瞻性的Ruby约定:
t = Test.new({:name => "something"})
t = Test.new(name: "something") # json-style or kwargs
但在你的例子中,你正在做的事情用=
让我们看起来更象变量赋值尝试使用块而不是散列。 (您还使用Name
这将是Ruby的一个常量,我们将改变这一现状。)
t = Test.new { @name = "something" }
酷,现在让我们实际工作:
class BlockInit
def self.new(&block)
super.tap { |obj| obj.instance_eval &block }
end
end
class Test < BlockInit
attr_accessor :name
end
t = Test.new { @name = "something" }
# => #<Test:0x007f90d38bacc0 @name="something">
t.name
# => "something"
我们已经创建了一个该类使用构造函数接受一个块参数,该参数在新实例化的对象中执行。
因为你说过要避免使用initialize
,所以我将覆盖new
并呼吁super
从Object#new
获取默认行为。 通常我们会定义initialize
而不是,除了满足您的问题中的特定请求外,不建议使用此方法。
当我们将块传递给BlockInit
的子类时,我们可以做的不仅仅是设置变量......我们基本上只是将代码注入initialize
方法(我们正在避免编写)。如果您还想要一个initialize
方法,做其他的东西(如你在评论中提到的),你可以把它添加到Test
,甚至不用调用super
(因为我们的改变是不BlockInit#initialize
,而BlockInit.new
)
希望这一个非常具体和有趣的请求的创造性解决方案。
- 1. 初始化红宝石
- 2. 红宝石/黄瓜测试初始化
- 3. 红宝石类的计数初始化
- 4. 初始化红宝石散列问题
- 5. 红宝石初始化和自我
- 6. 红宝石未初始化不断
- 7. 红宝石自我。 vs @初始化
- 8. 红宝石未初始化的常量
- 9. 红宝石 - 未初始化的常量
- 10. 红宝石,未初始化不断
- 11. “在初始化块”未初始化不断Testdeck NameError(红宝石)
- 12. 未初始化的常量使用Twitter的红宝石宝石
- 13. 红宝石宝石devise无法生成初始化程序
- 14. 红宝石的SoundCloud宝石:未初始化不断的SoundCloud
- 15. 红宝石哈希初始值设定
- 16. 红宝石比较对象
- 17. 从对象红宝石
- 18. 红宝石和零对象
- 19. 红宝石显示对象
- 20. 红宝石修改对象
- 21. 红宝石宝石加载,但依然给人“未初始化的常量”
- 22. 红宝石初始化实例变量以外的方法
- 23. 红宝石2.1+关键参数初始化器语法
- 24. 红宝石未初始化不断的RecipesController ::食谱
- 25. 红宝石:质量初始化实例变量
- 26. NameError:未初始化的常量歌...编程红宝石
- 27. 红宝石元编程:初始化变量singleton_class
- 28. 初始化类的成员变量失去价值红宝石
- 29. 如何初始化三维红宝石阵列
- 30. 红宝石:打电话给别人之前初始化方法
排除初始化方法(这是你的意思?)使事情变得困难。在创建新的'Test'对象时,'name'是否每次都得到相同的初始化?还是应该得到在开放代码中指定的值? – DigitalRoss
的动机是做类似于C#的东西 - http://msdn.microsoft.com/en-us/library/bb384062.aspx –
有什么你不喜欢与我提出的解决方案? –