Home > Back-end >  Why isn't it allowing my arguments in line 22?
Why isn't it allowing my arguments in line 22?

Time:04-09

    class Mage
    def initialize
        @name = name
        @level = level
        @power = power
        @element = element
    end
    def change=(n, l, p, e)
        self.name = n
        self.lvl = l
        self.power = p
        self.element = e
    end
    def stats
        puts "#{self.name}"
        puts "#{self.level}"
        puts "#{self.power}"
        puts "#{self.element}"
    end
end
aseas = Mage.new
aseas.change=("Aseas", 1, 1, "Fire")
aseas.stats

i have no idea whats wrong with it. if you can figure it out i'd greatly appreciate it. this code is just for practice btw

CodePudding user response:

Your code has several issues and might not be complete, but I assume you are referring to this line:

aseas.change=("Aseas", 1, 1, "Fire")

which is supposed to invoke this method:

def change=(n, l, p, e)
  # ...
end

The problem with this code is that you can only assign one value, e.g.:

foo = 1
foo #=> 1

When passing multiple values in an assignment, Ruby will wrap them in an array and assign that array instead: (the so-called implicit array assignment)

foo = 1, 2, 3
foo #=> [1, 2, 3]

The same applies to assignment methods and your method can't do anything about it. The only way to actually pass multiple arguments to an assignment method is to not use the assignment syntax but resort to send or public_send, i.e.

aseas.public_send(:change=, "Aseas", 1, 1, "Fire")

which you probably don't want to do, because it ruins the clean syntax.

There are several ways to fix your problem:

Use the implicit array as-is

Pass multiple values and let Ruby convert them to an array, let your method take the array and fetch the values from its elements:

def change=(ary)
  @name = ary[0]
  @level = ary[1]
  @power = ary[2]
  @element = ary[3]
end

aseas.change = "Aseas", 1, 1, "Fire"

# same as

aseas.change = ["Aseas", 1, 1, "Fire"]

Use the implicit array but decompose it

Same as above, but use array decomposition in your method to assign the array elements back to variables: (note the double parentheses)

def change=((name, level, power, element))
  @name = name
  @level = level
  @power = power
  @element = element
end

aseas.change = "Aseas", 1, 1, "Fire"

Don't use an assignment in the first place

You could just remove the = and be good to go:

def change(name, level, power, element)
  @name = name
  @level = level
  @power = power
  @element = element
end

aseas.change("Aseas", 1, 1, "Fire")

Don't use an assignment, keyword edition

A little more typing, but no ambiguity:

def change(name:, level:, power:, element:)
  @name = name
  @level = level
  @power = power
  @element = element
end

aseas.change(name: "Aseas", level: 1, power: 1, element: "Fire")

CodePudding user response:

When I run your code on my machine I get the following error:

in `initialize': undefined local variable or method `name' for 
#<Mage:0x00000001083a5738> (NameError)

This means the aseas = Mage.new is failing because something is wrong in the initialize method.

Looking at the initialize method

def initialize
    @name = name
    @level = level
    @power = power
    @element = element
end

we see that you try to assign name to @name, but a local variable or method name does not exist because you didn't pass it in.

Just change your initialize method to this:

def initialize(name, level, power, element)
    @name = name
    @level = level
    @power = power
    @element = element
end

And call it like this:

aseas = Mage.new("Aseas", 1, 1, "Fire")

Additionally, you are missing getter methods for the attributes and therefore the aseas.stats call will fail next. To fix that just add this line to your class

class Mage
  attr_reader :name, :level, :power, :element

or call the instance variable directly in the stats method like this:

def stats
    puts "#{@name}"
    puts "#{@level}"
    puts "#{@power}"
    puts "#{@element}"
end

CodePudding user response:

The line aseas = Mage.new will fail. The implementation of the initialize method is trying to access some variables that haven't been defined. As an example, the method does @name = name, but the variable name is not defined.

  •  Tags:  
  • ruby
  • Related