我有一个班,Foo.我希望能够将构造函数传递给Foo实例,foo并返回相同的实例.
换句话说,我希望这个测试通过:
class Foo; end
foo = Foo.new
bar = Foo.new(foo)
assert_equal foo, bar
Run Code Online (Sandbox Code Playgroud)
谁知道我怎么能这样做?我试过这个:
class Foo
def initialize(arg = nil)
return arg if arg
end
end
foo = Foo.new
bar = Foo.new(foo)
assert_equal foo, bar # => fails
Run Code Online (Sandbox Code Playgroud)
但它不起作用.
救命?
编辑
因为有很多人要求我的理由:
我正在快速分析大量数据(很多TB),我将会有很多对象的实例.对于其中一些对象,使用相同数据的两个不同实例没有意义.例如,一个这样的对象是具有两个属性的"窗口"(如在时间窗口中)对象:开始时间和结束时间.我希望能够以任何这些方式使用构造函数并获取一个窗口对象:
window = Window.new(time_a, time_b)
window = Window.new([time_a, time_b])
window = Window.new(seconds_since_epoch_a, seconds_since_epoch_b)
window = Window.new(window_obj)
window = Window.new(end => time_b, start => time_a)
...
Run Code Online (Sandbox Code Playgroud)
需要窗口的其他一些对象可能会以这种方式实例化:
obj = SomeObj.new(data => my_data, window => window_arg)
Run Code Online (Sandbox Code Playgroud)
我不一定知道window_arg中有什么,我真的不在乎 - 它会接受Window构造函数可以解释的任何单个参数.在已经有Window实例的情况下,我宁愿只使用该实例.但是解释这个问题的工作似乎是Window构造函数的一个问题.无论如何,正如我所提到的,我正在翻阅许多TB数据并创建大量实例.如果窗口对象被传递,我希望它只是被识别为窗口对象并被使用.
Jac*_*kin 30
通过定义,构造函数是为了回报他们的成员类的新创建的对象,所以,不应该不覆盖此行为.
此外,在Ruby中,在其方法体内的某处new调用initialize,并忽略其返回值,因此无论从哪种方式返回的值initialize都不会返回new.
话虽如此,我认为在您的情况下,您可能希望创建一个工厂方法,该方法将Foo根据传递给工厂方法的参数返回不同的对象:
class Foo
def self.factory(arg = nil)
return arg if arg.kind_of? Foo
Foo.new
end
end
foo = Foo.factory
bar = Foo.factory(foo)
assert_equal foo, bar #passes
Run Code Online (Sandbox Code Playgroud)
sep*_*p2k 15
initialize被调用new,忽略它的返回值.基本上默认new方法看起来像这样(除了它在C中实现,而不是在ruby中):
class Class
def new(*args, &blk)
o = allocate
o.send(:initialize, *args, &blk)
o
end
end
Run Code Online (Sandbox Code Playgroud)
因此无论你做什么,都会以任何一种方式返回新分配的对象initialize.更改new方法的唯一方法是覆盖方法,例如:
class Foo
def self.new(arg=nil)
if arg
return arg
else
super
end
end
end
Run Code Online (Sandbox Code Playgroud)
但是我强烈反对这一点,因为它违背了人们在致电时的许多期望new:
new返回一个新对象.我的意思是它甚至被称为new.如果您想要一个并不总是创建新对象的方法,您可能应该将其称为其他方法.Foo.new返回一个Foo物体.您的代码将返回任何参数.即Foo.new(42)返回42,一个整数,而不是一个Foo对象.因此,如果你要这样做,你应该至少只返回给定的对象,如果它是一个Foo对象.