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.