Different methods for initializing one object?


#1

Hi,
let’s say I’ve got a class Point2D to write, it must have 2 methods to
initialize :

  1. one with cartesian coordinates i.e : p = Point2D.new(x,y) given the
    numbers x and y;
  2. a second with polar coordinates i.e : p = Point2D.new(R,theta) given
    the radius R>0 and an angle theta;
    How can I manage this ?

Thanks.


#2

kibleur.christophe wrote:

Hi,
let’s say I’ve got a class Point2D to write, it must have 2 methods to
initialize :

  1. one with cartesian coordinates i.e : p = Point2D.new(x,y) given the
    numbers x and y;
  2. a second with polar coordinates i.e : p = Point2D.new(R,theta) given
    the radius R>0 and an angle theta;
    How can I manage this ?

One way would be to take keyword arguments and figure out which you were
given.

class Point2D
def initialize( params )
if params.has_key? :r and params.has_key? :theta
## initialize from polar
elsif params.has_key? :x and params.has_key? :y
## initialize from cartesian
else
raise ArgumentError.new( “You must provide either :r and :theta OR
:x and :y” )
end
end
end

cart = Point2D.new( :x => 42, :y => -4 )
polar = Point2D.new( :r => 3.14159, :theta => (Math::PI/4) )


#3
 raise ArgumentError.new( "You must provide either :r and :theta OR 

:x and :y" )
end
end
end

cart = Point2D.new( :x => 42, :y => -4 )
polar = Point2D.new( :r => 3.14159, :theta => (Math::PI/4) )

Hi Mike,

What you’ve proposed is a fine idea, but I think that it’s important to
be clear about your terminology. Ruby doesn’t currently have keyword
arguments. In the example that you’ve provided you are passing a hash
with symbols for keys into the initialize method and not using
keywords.

Regards,
Matthew J Desmarais


#4

desmarm wrote:

What you’ve proposed is a fine idea, but I think that it’s important to
be clear about your terminology. Ruby doesn’t currently have keyword
arguments. In the example that you’ve provided you are passing a hash
with symbols for keys into the initialize method and not using
keywords.

Oop, you’re of course correct. It’s more “I can’t believe it’s not
keyword arguments”, now with 30% less calories than regular argument
passing (yum, syntactic sugar!).


#5

You can also define alternate constructors:

class Point2D

class << self

  def new_xy( x, y )
    new.set_xy( x, y )
  end

  def new_rt( r, t )
    new.set_rt( r, t )
  end

end

def set_xy( x, y )
  @x, @y = x, y
end

def set_rt( r, t )
  @r, @t = r, t
end

end

p = Point2D.new_xy( x, y )
p = Point2D.new_rt( R, theta )

T.


#6

Quoting Mike F. removed_email_address@domain.invalid:

the radius R>0 and an angle theta;
How can I manage this ?

If you are always storing cartesian coordinates internally, I’d
suggest introducing a different factory method for creating points
from polar coordinates. For example:

class Point2D
attr_accessor :x, :y

def initialize( x, y )
@x, @y = x, y
end

def self.new_polar( r, theta )
new( r * Math::cos( theta ), r * Math::sin( theta ) )
end
end

examples:

cart = Point2D.new( 42, -4 )
polar = Point2D.new_polar( 3.14159, Math::PI / 4 )

-mental


#7

Thanks for all your answers, in fact, my class was already written with
the last mentioned code method.

class Point

attr_accessor :abs, :ord, :name, :cart

def initialize(abs,ord,name="")
@abs = abs
@ord = ord
@name = name
@cart = true
end

def to_s
“#@name : (#{@abs}, #{@ord})”
end

def ==(unPoint)
unPoint.abs = abs and unPoint.ord = ord
end

def Point.new_polaire(rho, theta, name)
@cart = false
@name = name
unPoint = new(rhocos(theta),rhosin(theta),@name)
return unPoint
end

end

…but I dislike the calling syntax. I thought it was possible to write
several constructors calls like in Java, ie :

void Move(Vector2D vector) {
    center.x += vector.x;
    center.y += vector.y;
}

void Move(double x,double y) {
    center.x += x;
    center.y += y;
}

So, my idea was bad : Ruby is not Java !