views:

538

answers:

3

I have this code:

def setVelocity (x, y, yaw)
  setVelocity (Command2d.new(x,y,yaw))
end
def setVelocity (vel)
......
end

vel is a Command2D class that has 3 attributes, is Comparable and defines + , basically is a convenient class for me to manage those 3 attributes, so I want to use it internally in my library (dont want to make them private, either give them weird names). But Ruby seems to keep only the last setVelocity even when the number of parameters is different. so when I call setVelocity with 3 parameters will say that I need to call that method with only one parameter.

+9  A: 

Ruby doesn't really support overloading.

This page gives more details and a workaround. Basically you create a single method with a variable number of parameters, and deal with them appropriately.

(I'd personally recommend writing one method to recognise the two different "faked overloads" and then one method for each overload, with different names reflecting the different parameters.)

Alternatively, just provide different names to start with :)

Jon Skeet
Truly, there is not a topic you are not present in. sensei Skeet - how is it you don't have a "generalist" badge? As of writing, you have posted in 2140 different tags, and the top 50 tags have at least 30 posts. Makes me wonder what it really takes to be a "generalist"
Matt
Yeah, generalist hasn't been implemented yet - Jeff has implied on Meta that he isn't going to do it directly, but something similar.
Jon Skeet
A: 

Use attr_accessor to add attributes and you will get getters and setters automatically. Alternatively use attr_reader or attr_writer to get read-only or write-only attributes.

class Foo
  attr_accessor :velocity
end

You can now set and get the value of this attribute like this:

foo = Foo.new
foo.velocity = 100
puts foo.velocity  # => 100

If you want to add methods to set the attribute based on some parameters, use a name reflecting what kind of input are expected:

def velocity_from_yaw(x, y, yaw)
  velocity = Command2d.new(x, y, yaw)
end

You can probably find a much better name in this case, but I don't know what your x, y and yaw really mean in your context.

Lars Haugseth
+1  A: 

Just for comparison, here's how I would solve it:

#!/usr/bin/env ruby

class Command2D
  def initialize(x, y, yaw)
    @command = [x, y, yaw]
  end
end

class Vehicle
  def velocity=(command_or_array)
    case command_or_array
    when Command2D
      self.velocity_from_command = command_or_array
    when Array
      self.velocity_from_array = command_or_array
    else
      raise TypeError, 'Velocity can only be a Command2D or an Array of [x, y, yaw]'
    end
  end

  private

  def velocity_from_command=(command)
    @velocity = command
  end

  def velocity_from_array=(ary)
    raise TypeError, 'Velocity must be an Array of [x, y, yaw]' unless ary.length == 3
    @velocity = Command2D.new(*ary)
  end
end

v1 = Vehicle.new
v1.velocity = Command2D.new(1, 2, 3)

v2 = Vehicle.new
v2.velocity = [1, 2, 3]

p v1
p v2
Jörg W Mittag