我有一个班,Foo。我希望能够将构造函数传递给Foo实例,foo并将相同的实例取回。
换句话说,我希望这个测试通过:
class Foo; end
foo = Foo.new
bar = Foo.new(foo)
assert_equal foo, bar
任何人都知道我该怎么做?我试过这个:
class Foo
def initialize(arg = nil)
return arg if arg
end
end
foo = Foo.new
bar = Foo.new(foo)
assert_equal foo, bar # => fails
但它不起作用。
帮助?
修改
因为有很多人要求我提出理由:
我正在快速分析大量数据(很多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)
...
需要窗口的其他一些对象可能会以这种方式实例化:
obj = SomeObj.new(data => my_data, window => window_arg)
我不一定知道window_arg中有什么,我真的不在乎 - 它会接受任何可由Window构造函数解释的参数。在已经有Window实例的情况下,我宁愿只使用该实例。但是解释这个问题的工作似乎是Window构造函数的一个问题。无论如何,正如我所提到的,我正在翻阅许多TB数据并创建大量实例。如果窗口对象被传递,我希望它只是被识别为窗口对象并被使用。
答案 0 :(得分:29)
通过definition,构造函数意味着返回它们所属的类的新创建的对象,因此,不应该不覆盖此行为。
此外,在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
答案 1 :(得分:17)
def Foo.new(arg=nil)
arg || super
end
答案 2 :(得分:15)
initialize
调用 new
,忽略其返回值。基本上,默认的new
方法看起来像这样(除了它在C中实现,而不是在ruby中):
class Class
def new(*args, &blk)
o = allocate
o.send(:initialize, *args, &blk)
o
end
end
所以无论你在initialize
做什么,都会以任何一种方式返回新分配的对象。改变它的唯一方法是覆盖new
方法,例如:
class Foo
def self.new(arg=nil)
if arg
return arg
else
super
end
end
end
但是我强烈反对这一点,因为它与人们在致电new
时的许多期望背道而驰:
new
返回一个新对象。我的意思是它甚至被称为new
。如果你想要一个并不总是创建一个新对象的方法,你应该把它称之为其他东西。Foo.new
返回Foo
个对象。您的代码将返回任何参数。即Foo.new(42)
将返回42,一个整数,而不是Foo
个对象。因此,如果你要这样做,你应该至少只返回给定的对象,如果它是Foo
对象。答案 3 :(得分:2)
不起作用:
class Some
def self.new( str )
SomeMore.new( str )
end
end
#
the Some is parent of SomeMore
class SomeMore < Some
def initialize( str )
@str = str
end
end
答案 4 :(得分:0)
对于这个特定用例,最好使用其中一种方法。
Class Foo
def self.new(args=nil)
@@obj ||= super(args)
end
end
Class Foo
def self.new(args)
@@obj = super(args)
end
def self.new
@@obj
end
end
这允许您只创建一个可以普遍使用的对象,但返回一个Foo
对象,使其更符合new
方法的标准期望,如雅各布指出。
答案 5 :(得分:0)
我偶然发现了这个问题,并且效果很好。说您想要一个构造函数(无论出于何种原因)以返回浮点数:
class Decimal
# possibly a bug that this works
@@value =
def self.new(input)
if input.class == Integer
@@value = input.to_f
elsif input.class == Float
@@value = input
else
@@value = -1.0
end
end
end
x = Decimal.new(4)
y = Decimal.new(32.141)
puts x # 4.0
puts y # 32.141
或者就您而言,Foo:
class Foo
@@value =
def self.new(args)
# some code ...
@@value = Foo.new #:<= your return value goes here
end
end