Overloaded constructors in Ruby

K

Kyle Heon

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
(e-mail address removed)
 
T

Timothy Hunter

Kyle said:
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

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)
 
T

Trans

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.
 
P

Phil Tomson

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

def GravPoint.from_x_y_strength(x,y,strength)
new(x,y,strength)
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
 
S

Sam Kong

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
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,754
Messages
2,569,527
Members
44,997
Latest member
mileyka

Latest Threads

Top