# Why should initialize\_copy verify the class of the original?

**URL:** <https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983>\
**Category:** Ruby\
**Created:** [February 18, 2007, 5:10pm UTC](https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983 "2007-02-18T17:10:44Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [February 18, 2007, 5:10pm UTC](https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983/1 "2007-02-18T17:10:44Z")

</div>

I was looking at the CD player example in the Pickaxe book and I can’t  
see why their C implementation of CDPlayer#initialize\_copy needs to  
check that the original object is an instance of CDPlayer . Isn’t  
this always the case? If #initialize\_copy is only called from inside  
#dup or #clone then surely the receiver has to be of the same class as  
the original! What am I missing?

Regards,

Jeremy H.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [February 18, 2007, 5:49pm UTC](https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983/2 "2007-02-18T17:49:50Z")

</div>

I can call initialize\_copy too, here:

object.initialize\_copy

Ha! I’ve fooled this object!

In Ruby, you can always do anything. No, really.

If $SAFE isn’t used (which is mostly the case), every bit of code can  
do ANYTHING to the program state.

So that initialize\_copy sanity test makes sense (personally, I’m not  
sure I would’ve done it, but it makes sense).

Plug: Check the adopt-a-newbie thread in ruby-talk.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [February 18, 2007, 7:10pm UTC](https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983/3 "2007-02-18T19:10:58Z")

</div>

On 2007-02-18, SonOfLilit [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I can call initialize\_copy too, here:
> 
> object.initialize\_copy

Well, actually you _can’t_:

```
==> NoMethodError: private method `initialize_copy' called for ...

```

🙂 but I take your point (and you can work round “private” with  
#instance\_eval ). But can it ever be called with an object of the  
wrong type unless the user explicitly does so?

> If $SAFE isn’t used (which is mostly the case), every bit of code can  
> do ANYTHING to the program state.

That’s true for Ruby variables, method calls etc., but hopefully we  
can ensure the C internals are not corrupted. I was thinking I could  
at least rely on the method being called with objects of the right  
type, but as you pointed out that’s not true.

> So that initialize\_copy sanity test makes sense (personally, I’m not  
> sure I would’ve done it,

I didn’t do it either when I implemented color classes for Ruby/FLTK.  
I haven’t managed to get a segfault out of it, but I can certainly  
corrupt objects. One more for the bug list…

Thanks for the answer, I’m a little embarrassed not to have thought of  
it before posting.

Jeremy H.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [February 19, 2007, 3:16pm UTC](https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983/4 "2007-02-19T15:16:52Z")

</div>

On Sun, 18 Feb 2007 17:10:06 +0100, Jeremy H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> I was looking at the CD player example in the Pickaxe book and I can’t  
> see why their C implementation of CDPlayer#initialize\_copy needs to  
> check that the original object is an instance of CDPlayer . Isn’t  
> this always the case? If #initialize\_copy is only called from inside  
> #dup or #clone then surely the receiver has to be of the same class as  
> the original! What am I missing?

CDPlayer.new.instance\_eval {initialize\_copy(TeddyBear.new)}

Which would probably cause the C implementation to do Bad Things without  
said check.

David V.

---

<div class="post-metadata">

**Author:** ![jeremyheiler](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/j/34f0e0/32.png) [@jeremyheiler](https://www.ruby-forum.com/u/jeremyheiler)\
**Post date:** [February 20, 2007, 10:31am UTC](https://www.ruby-forum.com/t/why-should-initialize-copy-verify-the-class-of-the-original/85983/5 "2007-02-20T10:31:01Z")

</div>

On 2007-02-19, David V. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> On Sun, 18 Feb 2007 17:10:06 +0100, Jeremy H. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
> wrote:
> 
> > […] If #initialize\_copy is only called from inside #dup or #clone  
> > then surely the receiver has to be of the same class as the  
> > original! What am I missing?
> 
> CDPlayer.new.instance\_eval {initialize\_copy(TeddyBear.new)}

That’s the conclusion we came to in the other thread (though it wasn’t  
written down explicitly as you did here).

> Which would probably cause the C implementation to do Bad Things  
> without said check.

Yes, if the instances of the CDPlayer and TeddyBear classes are T\_DATA  
objects that wrap (CDPlayer \*) and (TeddyBear \*) pointers, then this  
code will coerce a (TeddyBear \*) to a (CDPlayer \*). Hilarity may well  
ensue.

Incidentally the Pickaxe is (IMHO) a little misleading on this point,  
it describes Data\_Get\_Struct as “a type-safe wrapper around the macro  
DATA\_PTR(obj)”. In fact it’s only type-safe with respect to the TYPE  
of obj , it’s not type-safe with respect to the type of the C pointer  
that obj wraps.

Regards,

Jeremy H.
