[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

cloning object with array members

Shea Martin

1/5/2007 9:35:00 PM

Consider a simple class like this:
class MyClass
def initialize
@var1 = ''
@arr1 = []
end
end


Now if I have an instance of MyClass, and want to clone it, what is the
'cleanest' way to do this?

a = MyClass.new
b = a.clone

This method leaves 'b.arr1' pointing to the same data as a.arr1.

Hmmm... I'll try overriding clone, and manually deal with the arrays:

def clone
rslt = super.clone
end

This blows the stack, I believe because all methods are inherited virtually.

Ok, so now I have to manually copy everything in clone, whatever, I am
getting sick of this:

def clone
rslt = MyClass.new
rslt.var1 = @var1
rslt.arr1 = @arr1.clone
rslt
end

Turns out this does not compute either, as there is no method var1= or
arr1= ! I want to keep var1 private, so can't go this route either.


One more attempt:
def clone
rslt = MyClass.new

self.instance_variables.each do |member|
rslt.instance_variable_set( member,
self.instance_variable_get(member).clone )
end
end

This fails as the methos do not seem to copy over.

There has to be a simple way to do something like this? What is common
recipe for something like this? Should this really be that hard in ruby?

~S
11 Answers

dblack

1/5/2007 9:49:00 PM

0

Gary Wright

1/5/2007 9:53:00 PM

0


On Jan 5, 2007, at 4:40 PM, Shea Martin wrote:
> Hmmm... I'll try overriding clone, and manually deal with the arrays:
>
> There has to be a simple way to do something like this? What is
> common recipe for something like this? Should this really be that
> hard in ruby?

Warning: I didn't test these...

def clone
rslt = super # Use the default #clone instead of Myclass.new

instance_variables.each do |member|
rslt.instance_variable_set( member, instance_variable_get
(member).clone )
end

rslt
end

For your particular case you could avoid the loop of course:

def clone
rslt = super
rslt.instance_variable_set "@var1", @var1.clone
rslt.instance_variable_set "@arr1", @arr1.clone
rslt
end



Gary Wright




Olivier

1/5/2007 10:09:00 PM

0

> Hmmm... I'll try overriding clone, and manually deal with the arrays:
>
> def clone
> rslt = super.clone
> end
>
> This blows the stack, I believe because all methods are inherited
> virtually.

The method which must be overriden is initialize_copy

def initialize_copy(from)
@arr1 = from.instance_eval('@arr1').clone
end

--
Olivier Renaud

Shea Martin

1/6/2007 3:43:00 PM

0

Shea Martin wrote:
> Consider a simple class like this:
> class MyClass
> def initialize
> @var1 = ''
> @arr1 = []
> end
> end
>
>
> Now if I have an instance of MyClass, and want to clone it, what is the
> 'cleanest' way to do this?
>
> a = MyClass.new
> b = a.clone
>
> This method leaves 'b.arr1' pointing to the same data as a.arr1.
>
> Hmmm... I'll try overriding clone, and manually deal with the arrays:
>
> def clone
> rslt = super.clone
> end
>
> This blows the stack, I believe because all methods are inherited
> virtually.
>
> Ok, so now I have to manually copy everything in clone, whatever, I am
> getting sick of this:
>
> def clone
> rslt = MyClass.new
> rslt.var1 = @var1
> rslt.arr1 = @arr1.clone
> rslt
> end
>
> Turns out this does not compute either, as there is no method var1= or
> arr1= ! I want to keep var1 private, so can't go this route either.
>
>
> One more attempt:
> def clone
> rslt = MyClass.new
>
> self.instance_variables.each do |member|
> rslt.instance_variable_set( member,
> self.instance_variable_get(member).clone )
> end
> end
>
> This fails as the methos do not seem to copy over.
>
> There has to be a simple way to do something like this? What is common
> recipe for something like this? Should this really be that hard in ruby?
>
> ~S


Thanks for all the help. My last attempt at clone turns out to be fine,
I just forgot to return 'rslt'. That fixed everything.

~S

Pit Capitain

1/6/2007 5:43:00 PM

0

Shea, you found your answer in the meantime, but I wanted to show you
what was wrong with your other attempts:

>> a = MyClass.new
>> b = a.clone
>>
>> This method leaves 'b.arr1' pointing to the same data as a.arr1.

Yes, the default #dup and #clone create a shallow copy.

>> def clone
>> rslt = super.clone
>> end
>>
>> This blows the stack, I believe because all methods are inherited
>> virtually.

"super" isn't the same as in Java. super calls the same method of the
superclass, so what you are doing here is:

temp = super
rslt = temp.clone

Since temp is an instance of MyClass, you're calling clone again, which
gives you and endless recursion. The correct way would have been:

def clone
super
end

But this obviously doen't help you.

>> def clone
>> rslt = MyClass.new
>> rslt.var1 = @var1
>> rslt.arr1 = @arr1.clone
>> rslt
>> end
>>
>> Turns out this does not compute either, as there is no method var1= or
>> arr1= ! I want to keep var1 private, so can't go this route either.

The solution to this problem was:

>> def clone
>> rslt = MyClass.new
>>
>> self.instance_variables.each do |member|
>> rslt.instance_variable_set( member,
>> self.instance_variable_get(member).clone )
>> end
>> end
>>
>> This fails as the methos do not seem to copy over.

And here, as you've noted yourself, you just forgot to return your new
instance.

Regards,
Pit

Shea Martin

1/9/2007 9:35:00 PM

0

def clone
rslt = BuildConfig.new

self.instance_variables.each do |member|
rslt.instance_variable_set( member,
self.instance_variable_get(member).clone )
end

return rslt
end

This clone method bombs if any of the instance variables are FixNums,
Floats, boolean, etc. Is there a way in my loop to know if an instance
variable supports 'clone'?

~S

Stefano Crocco

1/9/2007 9:52:00 PM

0

Alle 22:35, martedì 9 gennaio 2007, Shea Martin ha scritto:
> def clone
> rslt = BuildConfig.new
>
> self.instance_variables.each do |member|
> rslt.instance_variable_set( member,
> self.instance_variable_get(member).clone )
> end
>
> return rslt
> end
>
> This clone method bombs if any of the instance variables are FixNums,
> Floats, boolean, etc. Is there a way in my loop to know if an instance
> variable supports 'clone'?
>
> ~S

I don't know whether there is a way to know in advance if a variable supports
clone, so I'd say: try it. If it works, good. If it doesn't, it'll raise an
exception, which you can rescue:

def clone
rslt = BuildConfig.new

self.instance_variables.each do |member|
begin rslt.instance_variable_set( member, self.instance_variable_get(member).clone )
rescue Exception: rslt.instance_variable_set(member, self.instance_variable_get(member))
end
end

return rslt
end

I'm not an expert, so there may be better ways to do this I don't know, but this should work.

Stefano

Ubiquitous

8/31/2010 5:06:00 PM

0

Tom

8/31/2010 5:56:00 PM

0

On Aug 31, 10:35 am, tomcervo <tomce...@aol.com> wrote:
> > Read more:http://newsbusters.org/blogs/nathan-burchfiel/2010/08/31/ov......
> > media-criticize-conservative-rallies-overwhel#ixzz0yBwxxVUM
>
> Now people won't think he's a right wing sock puppet plagiarist.
> Just a right wing sock puppet.

I'm shocked he posted a link, but not shocked that he and the author
of the article don't know the difference between observation and
criticism.

Tom

tomcervo

8/31/2010 6:28:00 PM

0

On Aug 31, 1:06 pm, Ubiquitous <web...@polaris.net> wrote:
> tomce...@aol.com wrote:
> >> Read
>
> more:http://newsbusters.org/blogs/nathan-burchfiel/2010/08/31/ov......
>
> >> media-criticize-conservative-rallies-overwhel#ixzz0yBwxxVUM
>
> >Now people won't think he's a right wing sock puppet plagiarist.
> >Just a right wing sock puppet.
>
> Ad hominum noted. Get back to us when you're able to offer a rebuttal about
> the content of the article.
>
> ---  
> "If Barack Obama isn't careful, he will become the Jimmy Carter of the 21st
> century."

I don't think that means what you think it means. If YOU are the
problem, with your endless, mindless Toadie-like spec cheerleading:

http://stars.ign.com/articles/823/823...

then it's not ad hominum. Get a new macro for your answerbot.