I learn the class with ruby and I have a question here.
I want to change the name of #name, like this ...
class User
attr_accessor :name
def initialize(name)
#name = name
end
def say_hello(a_user)
puts "The user #{#name} say hello at #{#name} !"
end
end
What I have
[1] pry(main)> user1 = User.new("Joe")
=> #<User:0x000055ebac183358 #name="Joe">
[2] pry(main)> user2 = User.new("Luis")
=> #<User:0x000055ebac11cb80 #name="Luis">
[3] pry(main)> user1.say_hello(user2)
=> The user Joe say hello at Joe !
And What I expect
=> The user Joe say hello at Luis !
Thank you for your help.
You can do something like this if I understand your problem correctly.
class User
attr_accessor :name
def initialize(name)
#name = name
end
def say_hello(user)
puts "The person #{#name} say hello at #{user.name} !"
end
end
Related
I've been trying to get this code to output:
'Mary has a pet called Satan.'
But what I get is:
'Mary has a pet called #<Cat:0x00000002784c20>'
Code Below:
class Person
def initialize(name)
#name = name
#pet = nil
#hobbies = []
end
def describe()
puts "This persons name is #{#name}."
puts "#{#name}'s hobbies are:"
#hobbies.map { |hobby| puts hobby }
if #pet == nil
puts "#{#name} has not got any pets."
else
puts "#{#name} has a pet called #{#pet}"
end
end
attr_accessor :pet, :hobbies
end
class Cat < Animal
def initialize(name)
#name = name
end
end
satan = Cat.new("Satan")
mary = Person.new("Mary")
mary.pet = satan
mary.describe
Thanks for all your help.
In your describe() function, you are calling the object Cat without specifing the name.
But if you call #{pet.name} it will throw:
<undefined method `name' for #<Cat:0x0055d750a1a450 #name="Satan">
You have to allow the access to the variable name in the Cat class first with attr_accessor
class Cat < Animal
attr_accessor :name # First allow access
end
class Person
def describe()
puts "#{#name} has a pet called #{#pet.name}" # Then call the pet's name!
end
end
I can't come up with a solution.
class Person
def initialize(name)
#name = name
end
def greet(other_name)
#other_name
print "Hi #{#other_name}, my name is #{#name}"
end
end
kit = Person.new("Tom", "Jerry")
kit.greet
I would appreciate a helping hand.
You have to make a decision:
Do you want to provide both names when initializing the Person:
class Person
def initialize(name, other)
#name = name
#other = other
end
def greet
puts "Hi #{#other}, my name is #{#name}"
end
end
kit = Person.new("Tom", "Jerry")
kit.greet
#=> Hi Jerry, my name is Tom
Or do you want to provide the second name when calling the greet method:
class Person
def initialize(name)
#name = name
end
def greet(other)
puts "Hi #{other}, my name is #{#name}"
end
end
kit = Person.new("Tom")
kit.greet("Jerry")
#=> Hi Jerry, my name is Tom
In the initialize method, you should take in two parameters, because you are calling it with two. You were declaring the #other_name variable inside the greet function instead of the initialize one.
This will work.
class Person
def initialize(name, other_name)
#name = name
#other_name = other_name
end
def greet
print "Hi #{#other_name}, my name is #{#name}"
end
end
kit = Person.new("Tom", "Jerry")
kit.greet
https://repl.it/C5wn
Consider writing your code like this:
class Person
attr_reader :name
def initialize(name)
#name = name
end
def greet(person)
puts "Hi #{person.name}, my name is #{name}"
end
end
tom = Person.new("Tom")
jer = Person.new("Jerry")
tom.greet(jer) #=> Hi Jerry, my name is Tom.
This way you actually have another person as an object instead of just a name.
I'm trying to get the code to print the name of a class and then greetings on the same line. For example:
(DriveThru): Hi, welcome to Starbucks! What can I get started for you?
Here's my code:
module Order
def order_drink
"(#{self.class.name}): #{self.greeting}"
end
end
class Lobby
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
puts "Hi, welcome to Starbucks! How are you doing today #{self.name}?"
end
end
class DriveThru
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
puts "Hi, welcome to Starbucks! What can I get started for you #{self.name}?"
end
end
dt = DriveThru.new("Tom")
lb = Lobby.new("Jessica")
puts dt.order_drink
puts lb.order_drink
When I run the code, it prints the greeting first, line breaks, then prints the class name like this:
"Hi, welcome to Starbucks! What can I get started for you?"
(DriveThru):
What am I'm doing wrong?
Your greeting function is executing the puts statement. Due to the way Ruby (and most other programming languages) works, the order_drink method will evaluate the contents of the greeting method (calling a puts statement) first before returning its own value.
Dropping the puts at the beginning of each greeting function, for example:
class Lobby
include Order
attr_reader :name
def initialize(name)
#name = name
end
def greeting
"Hi, welcome to Starbucks! How are you doing today #{self.name}?"
end
end
This will cause your script to output the following:
(DriveThru): Hi, welcome to Starbucks! What can I get started for you Tom?
(Lobby): Hi, welcome to Starbucks! How are you doing today Jessica?
That said, it'd be preferable to add an attr_reader for the greeting attribute, and set its value in the initialize method (also known as the constructor), like so:
class Lobby
include Order
attr_reader :name, :greeting
def initialize(name)
#name = name
#greeting = "Hi, welcome to Starbucks! How are you doing today #{name}?"
end
end
Well, I can do this:
class Person
attr_accessor :name
def greeting
"Hello #{#name}"
end
end
p = Person.new
p.name = 'Dave'
p.greeting # "Hello Dave"
but when I decide to assign the property in the class itself it doesnt work:
class Person
attr_accessor :name
#name = "Dave"
def greeting
"Hello #{#name}"
end
end
p = Person.new
p.greeting # "Hello"
This is the default behavior, albeit a confusing one (especially if you're used to other languages in the OOP region).
Instance variables in Ruby starts being available when it is assigned to and normally this happens in the initialize method of your class.
class Person
def initialize(name)
#name = name
end
end
In your examples you're using attr_accessor, this magical method produces a getter and a setter for the property name. A Person#name and Person#name=, method is created which overrides your "inline" instance variable (that's why your first example works and the second one doesn't).
So the proper way to write your expected behaviour would be with the use of a initialize method.
class Person
def initialize(name)
#name = name
end
def greeting
"Hello, #{#name}"
end
end
Edit
After a bit of searching I found this awesome answer, all rep should go to that question.
Think of a Person class as a blueprint that you can create single person instances with. As not all of these person instances will have the name "Dave", you should set this name on the instance itself.
class Person
def initialize(name)
#name = name
end
attr_accessor :name
def greeting
"Hello #{#name}"
end
end
david = Person.new("David")
p david.greeting
# => "Hello David"
mike = Person.new("Mike")
p mike.greeting
# => "Hello Mike"
I'd appreciate knowing why the instance of "Cat" below isn't also putting the "This animal can:" text before its specific instance attributes. I'm expecting an output like this:
This animal can:
Say it's name: 'Rover'
Bark
This animal can:
Say its name: 'Satan'
Meow
Here's the code:
class Animal
puts "This animal can:"
end
class Dog < Animal
def initialize(name)
#name = name
puts "Say its #name: '%s'" % [name]
end
def bark
puts "Bark"
end
end
class Cat < Animal
def initialize(name)
#name = name
puts "Say its #name: '%s'" % [name]
end
def meow
puts "Meow"
end
end
rover = Dog.new("Rover").bark
satan = Cat.new("Satan").meow
What I'm seeing is this:
This animal can:
Say it's name: 'Rover'
Bark
Say its name: 'Satan'
Meow
Doesn't "cat" also inherit from the Animal class? Shouldn't its output also begin with "This animal can:"?
The problem in your code is that:
puts "This animal can:"
is run when the Animal class gets defined. It seems like you want this in the initializer:
class Animal
def initialize(name)
puts "This animal can:"
end
end
You'll then need to call super in the other initializers for the result you're expecting.
The "This Animal can:" line only occurs when the class is defined, since it doesn't live in a method. Since both animals have common behavior in their initializers, you might want to promote the initializer to the Animal class.
class Animal
def introduce_myself
puts "Hello! My name is #{#name} and I know how to: "
end
def initialize(name)
#name = name
introduce_myself
end
end
class Dog < Animal
def bark
puts "Woof!"
end
end
class Cat < Animal
def meow
puts "Meow!"
end
end
Dog.new("Fido").bark
Cat.new("Sparky").meow
Output:
Hello! My name is Fido and I know how to:
Woof!
Hello! My name is Sparky and I know how to:
Meow!
Your Animal class doesn't define a constructor, nor is it called by inheritors:
class Animal
def initialize
puts "This animal can:"
end
end
class Dog < Animal
def initialize(name)
super()
#name = name
puts "Say its #name: '%s'" % [name]
end
def bark
puts "Bark"
end
end
Exactly!
class Animal
def initialize(name)
puts "This animal can:"
end
end
def initialize(name)
#name = name
puts "Say its #name: '%s'" % [name]
super # initializer from parent class
end
why that don't work ?
class Animal
puts "This animal can:"
end
when ruby parser read code it evaluate everything on way. I mean even if you will not create any object it will display "This animal can:" That's why you saw that for the first time and had impression that Dog class worked correctly
Install name_magic (gem install y_support) and have fun
require 'y_support/name_magic';
class Animal
include NameMagic
def initialize; puts "This animal #{sound}s." end
def sound; "growl" end
def speak; puts "#{sound.capitalize}!" end
end
class Dog < Animal
def sound; "bark" end
end
class Cat < Animal
def sound; "meow" end
end
def hullo( animal )
Animal.instance( animal ).speak
end
Rover = Dog.new
#=> This animal barks.
Satan = Cat.new
#=> This animal meows.
hullo :Rover
#=> Bark!
Animal.instances.each( &:speak )
#=> Bark!
#=> Meow!