Problems with literals and replacing classes

Hi all,

I’ve been trying to get some code working that restores original
versions of classes after they have been modified. I ran into a strange
problem, though; it seems that when you use literals, they don’t
respect which class is actually assigned to their class constant.
Here’s an example of the basic concept I’m looking at, which shows my
problem:

Add a method to String; returns nil

class String; def foo() end end

Backup a copy of String class

str = String.dup

Modify String#foo to return 23 instead of nil

class String; def foo() 23 end end

Test #foo method; should return nil

String.new.foo #=> 23
"".foo #=> 23

Restore String class from backup copy

String = str

Test #foo method. The first String class

doesn’t have it, so it should raise an error.

String.new.foo #=> nil
"".foo #=> 23

Why does the string literal use the old, modified version of the String
class? I did various tests, “”.class and String.new.class both return
String; but the two String classes have different ids. I can’t seem to
get the literals to use the new class; they always use the original
class.

Is this a bug? Is there any way around it? Am I doing something stupid?

cheers,
–Mark

It’s no bug. You have modified the String class object. This object
was bound to the String constant, but Ruby use this object, not the
String constant to create new instances.

Regards,

Michael

···

On Sat, May 15, 2004 at 03:53:15AM +0900, Mark Hubbart wrote:

Hi all,

I’ve been trying to get some code working that restores original
versions of classes after they have been modified. I ran into a strange
problem, though; it seems that when you use literals, they don’t
respect which class is actually assigned to their class constant.
Here’s an example of the basic concept I’m looking at, which shows my
problem:

Add a method to String; returns nil

class String; def foo() end end

Backup a copy of String class

str = String.dup

Modify String#foo to return 23 instead of nil

class String; def foo() 23 end end

Test #foo method; should return nil

String.new.foo #=> 23
“”.foo #=> 23

Restore String class from backup copy

String = str

Test #foo method. The first String class

doesn’t have it, so it should raise an error.

String.new.foo #=> nil
“”.foo #=> 23

Why does the string literal use the old, modified version of the String
class? I did various tests, “”.class and String.new.class both return
String; but the two String classes have different ids. I can’t seem to
get the literals to use the new class; they always use the original
class.

Is this a bug? Is there any way around it? Am I doing something stupid?

Well, that’s kinda what I’d figured it was doing. But still, I would
have thought that it would use the class defined in the String
constant. Is it really that expensive to do a lookup?

I’ll probably have to find another way to do what I’m trying for; maybe
using the ‘evil’ module to swap objects… But I really didn’t want to
have to do that.

thanks,
–Mark

···

On May 14, 2004, at 12:13 PM, Michael Neumann wrote:

Is this a bug? Is there any way around it? Am I doing something
stupid?

It’s no bug. You have modified the String class object. This object
was bound to the String constant, but Ruby use this object, not the
String constant to create new instances.