class A
def initialize
print "Hello! "
end
end
class B < A
def initialize(name)
super
print "My name is #{name}!"
end
end
test = B.new("Fred")
And I get
wrong number of arguments (1 for 0)
But why? Class B requires one argument, and I am giving it all right. Class A doesn't require any argument, so I am not passing anything through super at all.
You need to use super() in order to call it with no arguments. Super by itself automatically calls the parent with the arguments provided to itself (ie. "Name")
Related
To make a setter and a getter for Dessert class, I made the following code:
class Dessert
def initialize(name,calories)
#name=name
#calories=calories
end
def name
#name
end
def name=(names)
#name=names
end
def calories
#calories
end
def calories=(calory)
#calories=calory
end
end
d=Dessert.new("Salad",1200)
puts d.name("Khoresht")
puts d.calories(1600)
puts d.name()
puts d.calories()
The setter and getter must have the same name, and the compiler recognizes them by their signature. But here, I face the error:
`name': wrong number of arguments (1 for 0) (ArgumentError)
for the method name (the setter).
Why does it happen?
you should change d.name("Khoresht") to d.name=("Khoresht")
d=Dessert.new("Salad",1200)
d.name = "Khoresht" # use setter method, equal to d.name=("Khoresht")
d.calories = 1600
puts d.name
puts d.calories
The setter and getter have different name, in your codes, setter method name contains a =.
pangpang already answered your question. I just want to mention that it is uncommon in Ruby to define getter and setter methods.
Instead a common way is to use attr_accessor to declare getter and setter methods. The following example is equivalent to your code:
class Dessert
attr_accessor :name, :calories
def initialize(name, calories)
#name = name
#calories = calories
end
end
And other option might be to inherit from Struct. The following example has the same behaviour than your code:
class Dessert < Struct.new(:name, :calories)
end
What is the difference between calling super and calling super()? Which is the best one if the arguments passed to the child method don’t match what the parent is expecting.
When you call super with no arguments, Ruby sends a message to the parent of the current object, asking it to invoke a method with the same name as where you called super from, along with the arguments that were passed to that method.
On the other hand, when called with super(), it sends no arguments to the parent.
If the arguments you have don't match what the parent is expecting, then I would say you would want to use super(), or explicitly list parameters in the functional call to match a valid parent constructor.
Dictates arguments that are sent up the object ancestor chain
super - sends all arguments passed to the function to parent
super() - no arguments
super equals to super(*args), which brings all args to the inherited method
Use super() when you just want to call the method inherited from Parent without passing args
super example:
class Parent
def say(message)
p message
end
end
class Child < Parent
def say(message)
super
end
end
Child.new.say('Hello world!') # => "Hello world!"
super() examples:
class Parent
def say
p "I'm the parent"
end
end
class Child < Parent
def say(message)
super
end
end
Child.new.say('Hello!') # => ArgumentError (wrong number of arguments (given 1, expected 0))
class Parent
def say
p "I'm the parent"
end
end
class Child < Parent
def say(message)
super()
end
end
Child.new.say('Hi!') # => "I'm the parent"
I am very new to Ruby and I have been looking for an answer to my question, but haven't found an answer yet.
This is my code:
class Animal
def initialize(aName, anAge)
#name = aName
#age = anAge
end
end
class Cat < Animal
def initialize(aName, anAge, aBreed)
#breed = aBreed
super(aName, anAge, aBreed)
end
end
When I try to create a new cat object with defining three parameters, it says: ArgumentError: Wrong number of Arguments (3 for 2).
But when I do the same thing with two parameters I get (2 for 3).
I can't seem to figure it out...
Thanks for your help!
Your super class Animal constructor takes only two parameters aName and anAge. so you should only pass first two arguments of Cat to Animal.
class Cat < Animal
def initialize(aName, anAge, aBreed)
#breed = aBreed
super(aName, anAge)
end
end
I would like to access a class' name in its superclass MySuperclass' self.inherited method. It works fine for concrete classes as defined by class Foo < MySuperclass; end but it fails when using anonymous classes. I tend to avoid creating (class-)constants in tests; I would like it to work with anonymous classes.
Given the following code:
class MySuperclass
def self.inherited(subclass)
super
# work with subclass' name
end
end
klass = Class.new(MySuperclass) do
def self.name
'FooBar'
end
end
klass#name will still be nil when MySuperclass.inherited is called as that will be before Class.new yields to its block and defines its methods.
I understand a class gets its name when it's assigned to a constant, but is there a way to set Class#name "early" without creating a constant?
I prepared a more verbose code example with failing tests to illustrate what's expected.
Probably #yield has taken place after the ::inherited is called, I saw the similar behaviour with class definition. However, you can avoid it by using ::klass singleton method instead of ::inherited callback.
def self.klass
#klass ||= (self.name || self.to_s).gsub(/Builder\z/, '')
end
I am trying to understand the benefit of being able to refer to an anonymous class by a name you have assigned to it after it has been created. I thought I might be able to move the conversation along by providing some code that you could look at and then tell us what you'd like to do differently:
class MySuperclass
def self.inherited(subclass)
# Create a class method for the subclass
subclass.instance_eval do
def sub_class() puts "sub_class here" end
end
# Create an instance method for the subclass
subclass.class_eval do
def sub_instance() puts "sub_instance here" end
end
end
end
klass = Class.new(MySuperclass) do
def self.name=(name)
#name = Object.const_set(name, self)
end
def self.name
#name
end
end
klass.sub_class #=> "sub_class here"
klass.new.sub_instance #=> "sub_instance here"
klass.name = 'Fido' #=> "Fido"
kn = klass.name #=> Fido
kn.sub_class #=> "sub_class here"
kn.new.sub_instance #=> "sub_instance here"
klass.name = 'Woof' #=> "Woof"
kn = klass.name #=> Fido (cannot change)
There is no way in pure Ruby to set a class name without assigning it to a constant.
If you're using MRI and want to write yourself a very small C extension, it would look something like this:
VALUE
force_class_name (VALUE klass, VALUE symbol_name)
{
rb_name_class(klass, SYM2ID(symbol_name));
return klass;
}
void
Init_my_extension ()
{
rb_define_method(rb_cClass, "force_class_name", force_class_name, 1);
}
This is a very heavy approach to the problem. Even if it works it won't be guaranteed to work across various versions of ruby, since it relies on the non-API C function rb_name_class. I'm also not sure what the behavior will be once Ruby gets around to running its own class-naming hooks afterward.
The code snippet for your use case would look like this:
require 'my_extension'
class MySuperclass
def self.inherited(subclass)
super
subclass.force_class_name(:FooBar)
# work with subclass' name
end
end
I have a class:
class One
def initialize; end
end
I need to create a new class with my own constructor like this:
class Two < One
def initialize(some)
puts some
super
end
end
Two.new("thing")
but when I launch the code, I got an error:
thing
test.rb:10:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
super in this case (without parentheses) is a special form. It calls the superclass method with the original params.
Instead try calling
super()