0

In my module, I defined two functions have the same name but different number of arguments.

module MyMod
 def self.doTask(name:, age:)
    doTask(name: "John", age: 30, career: "Teacher")
 end

 def self.doTask(name:, age:, career:)
   puts "name:#{name}, age:#{age}, career:#{career}"
 end
end

As you see above, in doTask, I just call doTask.

In another Ruby file, I call the doTask by:

MyMod.doTask(name:"Kate", age: 28)

But I get runtime error:

unknown keyword: career (ArgumentError)

Why?

mikej
  • 65,295
  • 17
  • 152
  • 131
Leem.fin
  • 40,781
  • 83
  • 202
  • 354
  • When you're calling the method you're actually passing it a single hash as an argument, just so you know. – Sagar Pandya Sep 13 '16 at 07:42
  • 1
    @sagarpandya82 no. This is keyword arguments. See https://robots.thoughtbot.com/ruby-2-keyword-arguments – Pascal Sep 13 '16 at 07:44
  • @pascalbetz ah, thanks. – Sagar Pandya Sep 13 '16 at 07:48
  • "I defined two functions have the same name" – No, you didn't. First off, you didn't define functions, you defined *methods*, that's an extremely important distinction. Ruby doesn't have functions. Second, you defined a method, then you defined it again, overwriting the previous definition. – Jörg W Mittag Sep 13 '16 at 10:21

2 Answers2

4

Ruby does not have method overloading. You can not have multiple methods with the same name.

One solution would be to use a the three argument version of the method and add a default value for the :career argument.

module MyMod
  def self.doTask(name:, age:, career: "Teacher")
    puts "name:#{name}, age:#{age}, career:#{career}"
  end
end
MyMod.doTask(name:"Kate", age: 28)
MyMod.doTask(name:"Kate", age: 28, career: 'Teacher')
MyMod.doTask(name:"Kate", age: 28, career: 'Mechanic')
Pascal
  • 8,464
  • 1
  • 20
  • 31
2

Ruby doesn't support method overloading (2 methods with the same name and different parameters) so your second method definition with the career parameter is replacing the first method definition.

You can provide a default value for the optional parameter like this:

def self.doTask(name:, age:, career: 'Employee')
 puts "name:#{name}, age:#{age}, career:#{career}"
end

and then career will have the value "Employee" if not specified.

or default to nil and include some logic in the method body to handle

def self.doTask(name:, age:, career: nil)
  unless career.nil?
    # doTask with career
  else
    # doTask without career
  end
end

If you're coming to Ruby from another language like Java or C# then there's some great insight into why the equivalent behaviour doesn't exist in Ruby in this answer.

Community
  • 1
  • 1
mikej
  • 65,295
  • 17
  • 152
  • 131