I have a class, Foo. I want to be able to pass the constructor a Foo instance, foo and get the same instance back out.
In other words, I want this test to pass:
class Foo; end
foo = Foo.new
bar = Foo.new(foo)
assert_equal foo, bar
Anyone know how I can do that? I tried this:
class Foo
def initialize(arg = nil)
return arg if arg
end
end
foo = Foo.new
bar = Foo.new(foo)
assert_equal foo, bar # => fails
but it doesn't work.
Help?
EDIT
Because a number of people have asked for my rationale:
I'm doing rapid analysis of lots of data (many TB) and I am going to have a lot of instances of a lot of objects. For some of these objects, it doesn't make sense to have two different instances with the same data. For example, one such object is a "window" (as in temporal window) object that has two properties: start time and end time. I want to be able to use the constructor in any of these ways and get a window object back:
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)
...
Some other object that needs a window might be instantiated this way:
obj = SomeObj.new(data => my_data, window => window_arg)
I don't necessarily know what's in window_arg, and I don't really care -- it will accept any single argument that can be interpreted by the Window constructor. In the case of already having a Window instance, I'd rather just use that instance. But the job of interpreting that seems like a concern of the Window constructor. Anyway, as I mentioned I'm churning through many TB of data and creating lots of instances of things. If a window object gets passed around, I want it just to be recognized as a window object and used.
No, constructor does not return any value.
new is a class method, which generally creates an instance of the class (this deals with the tricky stuff like allocating memory that Ruby shields you from so you don't have to get too dirty). Then, initialize , an instance method, tells the object to set its internal state up according to the parameters requested.
Constructors are used to initialize the instance variables. In Ruby, the constructor has a different name, unlike other programming languages. A constructor is defined using the initialize and def keyword.
class → class. Returns the class of obj. This method must always be called with an explicit receiver, as class is also a reserved word in Ruby. 1. class #=> Fixnum self.
def Foo.new(arg=nil)
arg || super
end
By definition, constructors are meant to return a newly created object of the class they are a member of, so, no you should not override this behavior.
Besides, in Ruby, new
calls initialize
somewhere within its method body, and its return value is ignored, so either way the value you return from initialize
will not be returned from new
.
With that said, I think that in your case, you might want to create a factory method that will return different Foo
objects based on arguments passed to the factory method:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With