Forum: Ruby Overloaded constructors in Ruby

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
B6efa20772f1404cdd68840e95722891?d=identicon&s=25 kheon (Guest)
on 2005-12-06 02:24
(Received via mailing list)
I have a class that I want to have a number of overloaded constructors
for.

I tried doing something like this:

class GravPoint
    def initialize()
        this(0, 0, 0, 0, 0)
    end

    def initialize(x, y, strength)
        this(x, y, strength, 0, 0)
    end

    def initialize(x, y, strength, ctime, life)
        @x, @y, @strength, @ctime, @life = x, y, strength, ctime, life
    end
end

When I then run GravPoint.new() I get the following error:

GravPoint.rb:23:in `initialize': wrong number of arguments (0 for 5)
(ArgumentError)

I think I understand the error, it's expecting 5 arguments (based on the
last constructor) but I don't the "Ruby" way to set this up. What am I
missing?

I was able to get this to work, but was hoping that I could do it in a
format closer to the above to make it a little more flexible to use.

class GravPoint
    def initialize(x = 0, y = 0, strength = 0, ctime = 0, life = 0 )
        @x, @y, @strength, @ctime, @life = x, y, strength, ctime, life
    end
end

Kyle Heon
kheon@comcast.net
A70b7da5a3a712e800100e61ef8d8917?d=identicon&s=25 akonsu (Guest)
on 2005-12-06 02:32
(Received via mailing list)
i believe the way to do it is to use names parameters and/or default
values.
A47f52ca49a1db1ab137d60d962574b8?d=identicon&s=25 ces.fci (Guest)
on 2005-12-06 02:36
(Received via mailing list)
37a3c73ffbf864e4b28f7f2384ee12ce?d=identicon&s=25 Timothy Hunter (tim-hunter)
on 2005-12-06 03:20
(Received via mailing list)
Kyle Heon wrote:
>     end
> end

Actually, defining default values for arguments is a very "Ruby" way of
handling this case. If the arguments have sensible default values, then
I'd argue that it's the best solution. You could also use a hash to
simulate named parameters if that's what floats your boat. Another very
"Ruby" thing to do is to define multiple constructors with different
names.

Something I've done is to define a "basic" constructor and then define
one or more methods that modify the basic instance. For example, suppose
you have two kinds of rectangles, a regular square-cornered rectangle
and a rectangle with rounded corners. The difference between the two
rectangles is that the rounded rectangle needs an extra 2 numbers to
define the radii of the ovals that make up the corner. If you want a
plain rectangle just call "new". If you want a rounded rectangle, modify
the newly-constructed instance by calling "rounded" on it.

class Rectangle
    def initialize(width, height)
       @width, @height = width, height
    end

    def rounded(rx, ry)
       @rx, @ry = rx, ry
    end
end

rect = Rectangle.new(20, 30)
round_rect = Rectangle.new(20, 30).rounded(2, 3)
45196398e9685000d195ec626d477f0e?d=identicon&s=25 transfire (Guest)
on 2005-12-06 03:37
(Received via mailing list)
Timothy makes good points, but just so you understand how to write
alernate constructors for Ruby there are two weys.

First one can define alternate constructors:

  class GravPoint

    # however you wish to name them...

    def self.new_zero()
        new(0, 0, 0, 0, 0)
    end

    def self.new_lite(x, y, strength)
        new(x, y, strength, 0, 0)
    end

    def initialize(x, y, strength, ctime, life)
        @x, @y, @strength, @ctime, @life = x, y, strength, ctime, life
    end

  end

The other way is the use variable parameters. Something like:

     def initialize(*args)
        x, y, strength, ctime, life = 0,0,0,0,0
        case args.length
        when 0
          # good just the way it is, skip
        when 3
          x, y, strength = *args
        when 5
          x, y, strength, ctime, life = *args
        else
          raise ArgumentError
        end
        @x, @y, @strength, @ctime, @life = x, y, strength, ctime, life
     end

  T.
Eb9493c94d8db9887e5f15284d2c767f?d=identicon&s=25 ptkwt (Guest)
on 2005-12-06 08:29
(Received via mailing list)
In article <20051206012149.EF632339CD@beryllium.ruby-lang.org>,
Kyle Heon <kheon@comcast.net> wrote:
>        this(x, y, strength, 0, 0)
>(ArgumentError)
>        @x, @y, @strength, @ctime, @life = x, y, strength, ctime, life
>    end

     def GravPoint.from_x_y_strength(x,y,strength)
       new(x,y,strength)
     end

>end


gp = GravPoint.new #matches your first constructor
gp1= GravPoint.from_x_y_strength 5.5,4.2,254  #matches your 2nd c'tor
gp3= GravPoint.new(1,2,3,4,5) #matches your last c'tor

Phil
Ca0b18ec9e11dc777b2b8084fe5d5f90?d=identicon&s=25 sam.s.kong (Guest)
on 2005-12-06 18:05
(Received via mailing list)
Hi!

I guess you forgot a line, right?

class Rectangle
    def initialize(width, height)
       @width, @height = width, height
    end


    def rounded(rx, ry)
       @rx, @ry = rx, ry
       self #<-FORGOTTEN
    end
end


Sam
This topic is locked and can not be replied to.