0

I am writing the Ruby program found below

class Animal
  attr_reader :name, :age

  def name=(value)
    if value == ""
      raise "Name can't be blank!"
    end
    @name = value
  end

  def age=(value)
    if value < 0
      raise "An age of #{value} isn't valid!"
    end
    @age = value
  end

  def talk
    puts "#{@name} says Bark!"
  end

  def move(destination)
    puts "#{@name} runs to the #{destination}."
  end

  def report_age
    puts "#{@name} is #{@age} years old."
  end
end

class Dog < Animal
end

class Bird < Animal
end

class Cat < Animal
end

whiskers = Cat.new("Whiskers")
fido = Dog.new("Fido")
polly = Bird.new("Polly")
polly.age = 2
polly.report_age
fido.move("yard")
whiskers.talk

But when I run it, it gives this error:

C:/Users/akathaku/mars2/LearningRuby/Animal.rb:32:in `initialize': wrong number of arguments (1 for 0) (ArgumentError)
    from C:/Users/akathaku/mars2/LearningRuby/Animal.rb:32:in `new'
    from C:/Users/akathaku/mars2/LearningRuby/Animal.rb:32:in `<main>'

My investigations shows that I should create objects like this

whiskers = Cat.new("Whiskers")

Then there should be an initialize method in my code which will initialize the instance variable with the value "Whiskers".

But if I do so then what is the purpose of attribute accessors that I am using? Or is it like that we can use only one and if I have to use attribute accessors then I should avoid initializing the instance variables during object creation.

2

3 Answers 3

3

initialize is the constructor of your class and it runs when objects are created.

Attribute accessors are used to read or modify attributes of existing objects.

Parameterizing the constructor(s) gives you the advantage of having a short and neat way to give values to your object's properties.

whiskers = Cat.new("Whiskers")

looks better and it's easier to write than

whiskers = Cat.new
whiskers.name = "Whiskers"

The code for initialize in this case should look like

class Animal
  ...
  def initialize(a_name)
    name = a_name
  end
  ...
end
Sign up to request clarification or add additional context in comments.

1 Comment

You may want to show example of initialize for achieving that.
0

All attr_reader :foo does is define the method def foo; @foo; end. Likewise, attr_writer :foo does so for def foo=(val); @foo = val; end. They do not do assume anything about how you want to structure your initialize method, and you would have to add something like

def initialize(foo)
  @foo = foo
end

Though, if you want to reduce boilerplate code for attributes, you can use something like Struct or Virtus.

Comments

0

You should define a method right below your class name, something like

def initialize name, age
@name = name
@age = age
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.