Different methods for initializing one object?

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.

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

···

--
Posted via http://www.ruby-forum.com/\.

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.

<snip>

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

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

Quoting Mike Fletcher <lemurific+rforum@gmail.com>:

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 ?

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

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!).

···

--
Posted via http://www.ruby-forum.com/\.

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(rho*cos(theta),rho*sin(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 !