# User-defined class coercion?

**URL:** <https://rubytalk.org/t/user-defined-class-coercion/7239>\
**Category:** ruby-talk\
**Created:** [6 August 2003 03:00 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239 "2003-08-06T03:00:55Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Mark\_J\_Reed](https://avatars.discourse-cdn.com/v4/letter/m/f6c823/32.png) [@Mark\_J\_Reed](https://rubytalk.org/u/Mark_J_Reed)\
**Post date:** [6 August 2003 03:00 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/1 "2003-08-06T03:00:55Z")

</div>

I would like to define my own class that works as a number when  
treated as a number but also has other properties. Can I do this?  
If so, how?

-Mark

---

<div class="post-metadata">

**Author:** ![Yukihiro\_Matsumoto2](https://avatars.discourse-cdn.com/v4/letter/y/b9e5f3/32.png) [@Yukihiro\_Matsumoto2](https://rubytalk.org/u/Yukihiro_Matsumoto2)\
**Post date:** [6 August 2003 03:20 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/2 "2003-08-06T03:20:04Z")

</div>

Hi,

> I would like to define my own class that works as a number when  
> treated as a number but also has other properties. Can I do this?  
> If so, how?

By defining “coerce” method:

class Foo  
def coerce(other)  
…  
return converted\_other, self  
end  
end

```
						matz.

```

> **···**
>
> In message “User-defined class coercion?” on 03/08/06, “Mark J. Reed” [markjreed@mail.com](mailto:markjreed@mail.com) writes:

---

<div class="post-metadata">

**Author:** ![Dave\_Mail\_Archive](https://avatars.discourse-cdn.com/v4/letter/d/f04885/32.png) [@Dave\_Mail\_Archive](https://rubytalk.org/u/Dave_Mail_Archive)\
**Post date:** [6 August 2003 04:12 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/3 "2003-08-06T04:12:04Z")

</div>

Mark J. Reed wrote:

> I would like to define my own class that works as a number when  
> treated as a number but also has other properties. Can I do this?  
> If so, how?

Here’s an extract from the new reference material for the coerce method:

```
  Coerce is both an instance method of Numeric and part of a
  type conversion protocol. When a number is asked to perform an
  operation, and is passed a parameter of class different to its
  own, it must first coerce both itself and that parameter into a
  common class so that the operation makes sense. For example, in
  the expression $1 + 2.5$, the Fixnum ``1'' must be converted
  to a Float to make it compatible with ``2.5''. This
  conversion is performed by coerce. For all numeric
  object, coerce is straightforward: if aNumeric is the same
  type as self, returns an array containing aNumeric and
  self. Otherwise, returns an array with both aNumeric and
  self represented as Float objects.
 
  If a numeric object is asked to operate on a non-numeric, it
  tries to invoke coerce on that other object. For
  example, if you write:

      1 + "2"

 Ruby will effectively execute the code as:

      n1, n2 = "2".coerce(1)
      n2 + n1

  In the more general case, this won't work, as most non-numerics
  don't define a coerce method. However, you can use this
  (if you feel so inclined) to implement part of Perl's automatic
  conversion of strings to numbers in expressions.

    class String
      def coerce(other)
        case other
        when Integer
          begin
            return Integer(self), other
          rescue
            return Float(self), Float(other)
          end
        when Float
          return Float(self), other
        else super
        end
      end
    end

    1 + "2"
    1 + "2.3"
    1.2 + "2.3"
    1.5 + "2"

```

---

<div class="post-metadata">

**Author:** ![Mark\_J\_Reed](https://avatars.discourse-cdn.com/v4/letter/m/f6c823/32.png) [@Mark\_J\_Reed](https://rubytalk.org/u/Mark_J_Reed)\
**Post date:** [6 August 2003 03:41 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/4 "2003-08-06T03:41:01Z")

</div>

MR = me  
YM = Matz

> I would like to define my own class that works as a number when  
> treated as a number but also has other properties. Can I do this?  
> If so, how?

> By defining “coerce” method:
> 
> class Foo  
> def coerce(other)  
> …  
> return converted\_other, self  
> end  
> end

That works wonderfully. Thank you, for everything! Didn’t expect my  
dumb newbie question to be answered by the creator of the language. 🙂

-Mark

---

<div class="post-metadata">

**Author:** ![StephenSykes](https://avatars.discourse-cdn.com/v4/letter/s/0ea827/32.png) [@StephenSykes](https://rubytalk.org/u/StephenSykes)\
**Post date:** [6 August 2003 11:02 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/5 "2003-08-06T11:02:04Z")

</div>

> ```
> In the more general case, this won't work, as most non-numerics
> don't define a coerce method. However, you can use this
> (if you feel so inclined) to implement part of Perl's automatic
> conversion of strings to numbers in expressions.
> 
> class String
> def coerce(other)
> case other
> when Integer
> begin
> return Integer(self), other
> rescue
> return Float(self), Float(other)
> end
> when Float
> return Float(self), other
> else super
> end
> end
> end
> 
> 1 + "2"
> 1 + "2.3"
> 1.2 + "2.3"
> 1.5 + "2"
> 
> ```

But…

1 - “4” =\> 3  
1 - “2.4” =\> 1.4

The return values were the wrong way around, this should work better:

class String  
def coerce(other)  
case other  
when Integer  
begin  
return other, Integer(self)  
rescue  
return Float(other), Float(self)  
end  
when Float  
return other, Float(self)  
else super  
end  
end  
end

But even so…

8 | “16”  
TypeError: cannot convert String into Integer  
from (irb):47:in `|’  
from (irb):47  
from ❤:0

I feel it is an anomaly for the bitwise operators to not call coerce.  
Yes, it makes no sense to coerce to or from floats for bitwise, but  
there are other cases as the above shows.

Stephen  
± S.D.Sykes - [www.stephensykes.com](http://www.stephensykes.com)

> **···**
>
> > “You are a woman, aren’t you?” – The Duke of Edinburgh checks his  
> > facts after receiving a gift from a woman, Kenya 1984.

---

<div class="post-metadata">

**Author:** ![Mark\_Wilson](https://avatars.discourse-cdn.com/v4/letter/m/a3d4f5/32.png) [@Mark\_Wilson](https://rubytalk.org/u/Mark_Wilson)\
**Post date:** [6 August 2003 03:54 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/6 "2003-08-06T03:54:24Z")

</div>

And that’s only one of the many charms of Ruby. 🙂

I started out very enthusiastic about Ruby and it just keeps getting  
better. In some ways, encountering Ruby is like having a veil that was  
obscuring your vision lifted from your eyes.

Regards,

Mark

> **···**
>
> On Tuesday, August 5, 2003, at 11:41 PM, Mark J. Reed wrote:
> 
> > [snip]  
> > That works wonderfully. Thank you, for everything! Didn’t expect my  
> > dumb newbie question to be answered by the creator of the language.  
> > 🙂
> > 
> > -Mark

---

<div class="post-metadata">

**Author:** ![Dave\_Mail\_Archive](https://avatars.discourse-cdn.com/v4/letter/d/f04885/32.png) [@Dave\_Mail\_Archive](https://rubytalk.org/u/Dave_Mail_Archive)\
**Post date:** [6 August 2003 13:23 UTC](https://rubytalk.org/t/user-defined-class-coercion/7239/7 "2003-08-06T13:23:42Z")

</div>

haldane wrote:

> But…
> 
> 1 - “4” =\> 3  
> 1 - “2.4” =\> 1.4
> 
> The return values were the wrong way around, this should work better:

Oops - and I even documented that… sigh

Thanks

Dave
