What is wrong with this set/get?
class Pupil
def name
#name
end
def name=(name)
#name = name
end
def age
#age
end
def age=(age)
#age
end
end
Further on the same, if there was a child class with 3 arguments, name, age, sex, would the set get method in the child for sex only. Can you please show the set/get method and initialize in the child class.
def age=(age)
#age
end
should be
def age=(age)
#age = age
end
You can also make your code beautiful by replacing get/set with attr_accessor which itself provides a getter/setter
class Pupil
attr_accessor :age,:name
end
You forgot to set #age = age.
Related
Here's code that works but I'm looking to make it as clean as possible, to get the output without having to build a hash.
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
def create
Report.create({name: #name, age: #age})
end
end
class Report < Person
def self.create(attributes)
puts "Hello, this is my report. I am #{attributes[:name]} and my age is #{attributes[:age]}."
end
end
me = Person.new("Andy", 34)
me.create # Hello, this is my report. I am Andy and my age is 34.
Here are my changes that didn't work, but is there a method that would?
def create
Report.create
end
and
def self.create(attributes)
puts "Hello, this is my report. I am #{:name} and my age is #{:age}."
end
but the output was "I am name and my age is age."
You could just pass the person, something like this:
class Person
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
def report
Report.new(self)
end
end
class Report
attr_accessor :person
def initialize(person)
#person = person
end
def to_s
"Hello, this is my report. I am #{person.name} and my age is #{person.age}."
end
end
me = Person.new("Andy", 34)
puts me.report
# Hello, this is my report. I am Andy and my age is 34.
Note that I've changed some details:
Report doesn't inherit from Person
Report instances are created via new
Person#create is now Person#report
Report uses to_s for the output (which is called by puts)
Im a bit confused on the initialize method. I understand that it is automatically called when you do Person.new and you add the arguments to it like Person.new("james"). What I dont understand is, why would you have instance variables in your initialize method that are not an used as an argument also. Is it so you can use them later on after the instance has been created?
See below. What reason is there to have #age in the initialize method but not as an argument. thanks.
class Person
attr_accessor :name, :age
def initialize(name)
#name = name
#age = age
end
You can set an instance variable in any method in your class.
initialize is a method that is executed immediately after calling Person.new.
All external data for new object is passed through the arguments of .new(args).
Your line #age = age - it's the same that #age = nil.
This is due to the fact that age is absent in the arguments of initialize.
Also you have attr_accessor :age.
It's equal, that you have methods:
def age
#age
end
def age=(age)
#age = age
end
So you can set instance variable like this:
john = Person.new('John')
p john.age #=> nil
john.age = 5
p john.age #=> 5
The instance variables declared inside your initialize method only need to be those which you want to set during initialization. In your Person class example, you wouldn't need to set #age in initialization (it actually would throw an error as you currently have it).
class Person
attr_accessor :name, :age
def initialize(name)
#name = name
end
def birthday
if #age.nil?
#age = 1
else
#age += 1
end
end
end
Hopefully, this helps. If the initialize method doesn't have an age set, you can still use/set age in other methods. In this case, the first time the Person.birthday method is called, it would set their #age to 1, and then increment it from there.
For example if you need to call a method to assign a value to the instance variable while instantiating the object.
This is silly, but gives an idea:
class Person
attr_accessor :name, :age
def initialize(name)
#name = name
#age = random_age
end
def random_age
rand(1..100)
end
end
jack = Person.new('jack')
p jack.age #=> 29
Is replacing self.name.split with #name.split the same thing?
class Person
attr_accessor :name
def initialize(name)
#name = name
end
def normalize_name
self.name.split(" ").collect{|w| w.capitalize}.join(" ")
end
end
Yes it has the same outcome, because you defined a attr_accessor which gives you getter and setter methods
class Person
def name
#name
end
def name=(str)
#name = str
end
end
so you can call the function name using self receiver but if you get rid of the attr_accessor from your class you can't use self.name to get the value of name
class Person
def initialize(name)
#name = name
end
def normalize_name
self.name.split(" ").collect{|w| w.capitalize}.join(" ")
end
end
p = Person.new('John Doe')
p.normalize_name
NoMethodError: undefined method `name' for #<Person:0x00557e98300f68 #name="John Doe">
Im struggling on understanding (after googling) on how to implement this: I have a class:
class Student
# constructor method
def initialize(name,age)
#name, #age = name, age
end
# accessor methods
def getName
#name
end
def getAge
#age
end
# setter methods
def setName=(value)
#name = value
end
def setAge=(value)
#age = value
end
end
And lets say I have another class which inherits from Student
class Grade < Student
#constructor method
def initialize(grade)
super
#grade = grade
end
# accessor methods
def getGrade
#grade
end
# setter methods
def setGrade=(value)
#grade = value
end
end
I understand how to build an abject:
student = Student.new(name, age)
How can I build this Student (that I have just created) a Grade object associated with the student and how would I call the inherited object, for example i wanted to:
puts 'student name and associated grade'
I know I can place the grade variable within the Student class, but for the purpose of learning im doing it this way.
This code would do what you wanted:
class Grade
attr_accessor :value
def initialize value
#value = value
end
end
class Student
attr_accessor :name, :age, :grade
def initialize name, age, grade
#name, #age, #grade = name, age, Grade.new(grade)
end
end
st = Student.new 'John', 18, 5
puts "student #{st.name} and associated grade #{st.grade.value}"
First off, no need to define accessors in Ruby like that, it's far from idiomatic. Let's clean that up first:
class Student
attr_accessor :name, :age
def initialize(name, age)
#name =name
#age = age
end
end
class Grade
attr_accessor :value
def initialize(grade)
#value = grade
end
end
Secondly it doesn't seem like Grade should inherit from Student at all, just adjust the latter to also store a Grade instance variable:
class Student
attr_accessor :name, :age, :grade
def initialize(name, age, grade = nil)
#name =name
#age = age
#grade = grade
end
end
You can then instantiate a student like this:
student = Student.new("Test", 18, Grade.new(1))
Or because of the default value you leave off the grade and assign it later:
student = Student.new("Test", 18)
# later
student.grade = Grade.new(1)
The program below is an attempt to take in an American president, and French President's age, and name. The catch is that the French president says "bein sur" afterward calling his name, age and citizenship (not my idea). I'm having trouble with the French president's catchphrase. Here's my code
class President
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
end
class FrancePresident < President
def self.citizenship
"La France"
end
def initialize(name, age)
super(name, age)
end
def catchphrase
"bien sur"
end
def name
"#{name}, #{catchphrase}"
end
def age
"#{age}, #{catchphrase}"
end
def citizenship
"#{self.class.citizenship}, #{catchphrase}"
end
end
class UnitedStatesPresident < President
def self.citizenship
"The Unites States of America"
end
end
I think I'm referring to the superclass incorrectly because I'm receiving the stack error below.
SystemStackError
stack level too deep
exercise.rb:29
I'm new to Ruby, so any insight will be helpful.
Your name function generates infinite recursion, because it calls itself:
def name
"#{name}, #{catchphrase}" # <-- here, name calls this very function again and again
end
Same goes for age. They should call the instance variables, #name and #age, respectively:
def name
"#{#name}, #{catchphrase}"
end
def age
"#{#age}, #{catchphrase}"
end
Edit
It's probably better still to use super instead of the instance variables, because it makes it clear that you are using the functionality from the base class and adding something to it (Thanks for the tip, tadman!):
def name
"#{super}, #{catchphrase}"
end
def age
"#{super}, #{catchphrase}"
end
Here's the result based on all of your comments. Thanks for all your help!
class President
attr_accessor :name, :age
def initialize(name, age)
#name = name
#age = age
end
end
class FrancePresident < President
def self.citizenship
"La France"
end
def catchphrase
"bien sur"
end
def name
"#{#name}, #{catchphrase}"
end
def age
"#{#age}, #{catchphrase}"
end
def citizenship
"#{self.class.citizenship}, #{catchphrase}"
end
end
class UnitedStatesPresident < President
def self.citizenship
"The Unites States of America"
end
end