Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Hi Marty,
- Looking at your code, I notice first off that you've got some unnecessary lines.
- attr_reader
- attr_writer
- attr_accessor
- You don't need all 3 of these.
- Let's take a quick look at what this does.
- class Student
- attr_reader :name
- def initialize(name)
- @name = name
- end
- end
- attr_reader in the above case, will add the attribute 'name' to the class, ever instance of the Student class will have an attribute named 'name' attached to it. It also creates a method on the Student class that will return the value of the name attribute. The name attribute is stored inside of a special variable called an 'instance' variable. An instance variable is a variable in Ruby beginning with an @ and it's available in scope to the entire instance of the class.
- So, if we continue the above code with...
- student_one = Student.new("Marty Carr") # => #<Student:0x00555615cec618 @name="Marty Carr">
- puts student_one.name # >> Marty Carr
- However, right now if you were to try...
- student_one.name = "Bob Bobertson" # ~> -:13:in `<main>': undefined method `name=' for #<Student:0x0055c608151d18 @name="Marty Carr"> (NoMethodError)
- Why's this? It's because the attr_reader helper doesn't define a method for setting the instance variable, it only defines a method for accessing it.
- Let's alter the above sample code a tiny bit, and make it an attr_writer instead.
- class Student
- attr_writer :name
- def initialize(name)
- @name = name
- end
- end
- student_one = Student.new("Marty Carr") # => #<Student:0x0055697acd9a18 @name="Marty Carr">
- student_one.name = "Bob Bobertson" # => "Bob Bobertson"
- puts student_one.name # ~> -:12:in `<main>': undefined method `name' for #<Student:0x005563ba9bfcf8 @name="Bob Bobertson"> (NoMethodError)
- See what happened this time? You've now got a method for name= which will set @name on the class, but, no method for reading the attribute back out. You could add this manually by defining...
- class Student
- attr_writer :name
- def initialize(name)
- @name = name
- end
- def name
- @name
- end
- end
- student_one = Student.new("Marty Carr") # => #<Student:0x005579784ff758 @name="Marty Carr">
- student_one.name = "Bob Bobertson" # => "Bob Bobertson"
- puts student_one.name # >> Bob Bobertson
- So, lastly, there's a helper for if you need/want/desire both functionalities, and that's the attr_accessor helper.
- class Student
- attr_accessor :name
- def initialize(name)
- @name = name
- end
- end
- student_one = Student.new("Marty Carr") # => #<Student:0x005586035ebe18 @name="Marty Carr">
- student_one.name = "Bob Bobertson" # => "Bob Bobertson"
- puts student_one.name # >> Bob Bobertson
- See how that works?
- Now, one of the examples you gave was calculating an average score across multiple students. So, to keep things simple, let's take our above code, and give an instance of Student a score.
- class Student
- attr_accessor :name, :score
- def initialize(name, score)
- @name = name
- @score = score
- end
- end
- students = []
- students << Student.new("Marty Carr", 100) # => [#<Student:0x005560a72fb900 @name="Marty Carr", @score=100>]
- students << Student.new("Bob Bobertson", 77) # => [#<Student:0x005560a72fb900 @name="Marty Carr", @score=100>, #<Student:0x005560a72fb310 @name="Bob Bobertson", @score=77>]
- students << Student.new("George Carlson", 83) # => [#<Student:0x005560a72fb900 @name="Marty Carr", @score=100>, #<Student:0x005560a72fb310 @name="Bob Bobertson", @score=77>, #<Student:0x005560a72fad20 @name="George Carlson", @score=83>]
- At this point, we've got three students, and we want an average of their scores.
- We can do...
- class Student
- attr_accessor :name, :score
- def initialize(name, score)
- @name = name
- @score = score
- end
- end
- students = []
- students << Student.new("Marty Carr", 100) # => [#<Student:0x0055a0fba24bc0 @name="Marty Carr", @score=100>]
- students << Student.new("Bob Bobertson", 77) # => [#<Student:0x0055a0fba24bc0 @name="Marty Carr", @score=100>, #<Student:0x0055a0fba244b8 @name="Bob Bobertson", @score=77>]
- students << Student.new("George Carlson", 83) # => [#<Student:0x0055a0fba24bc0 @name="Marty Carr", @score=100>, #<Student:0x0055a0fba244b8 @name="Bob Bobertson", @score=77>, #<Student:0x0055a0fb977e70 @name="George Carlson", @score=83>]
- number_of_students = students.count # => 3
- students.map { |student| student.score }.reduce(0) { |sum, x| sum + x / number_of_students.to_f }
- # => 86.66666666666667
- To get a better picture of the above, I'll break it apart.
- scores = students.map { |student| student.score } # => [100, 77, 83]
- total = scores.reduce(0) { |sum, x| sum + x } # => 260
- total / number_of_students # => 86
- total / number_of_students.to_f # => 86.66666666666667
- Pretty cool, huh?
- Let's say you wanted to do multiple classrooms now. You probably wouldn't make the students responsible for tracking the classroom, we might have something else for that.
- class Classroom
- attr_accessor :students, :name
- def initialize(name)
- @students = []
- @name = name
- end
- def add_student(student)
- @students << student
- end
- def average
- @students.map { |student| student.score }.reduce(0) { |sum, x| sum + x / @students.count.to_f }
- end
- end
- class Student
- attr_accessor :name, :score
- def initialize(name, score)
- @name = name
- @score = score
- end
- end
- a = Student.new("Marty Carr", 100) # => #<Student:0x0055e86b908130 @name="Marty Carr", @score=100>
- b = Student.new("Bob Bobertson", 77) # => #<Student:0x0055e86b902118 @name="Bob Bobertson", @score=77>
- c = Student.new("George Carlson", 83) # => #<Student:0x0055e86b9002c8 @name="George Carlson", @score=83>
- room_one = Classroom.new "Science"
- room_one.add_student(a) # => [#<Student:0x0055e86b908130 @name="Marty Carr", @score=100>]
- room_one.add_student(b) # => [#<Student:0x0055e86b908130 @name="Marty Carr", @score=100>, #<Student:0x0055e86b902118 @name="Bob Bobertson", @score=77>]
- room_one.add_student(c) # => [#<Student:0x0055e86b908130 @name="Marty Carr", @score=100>, #<Student:0x0055e86b902118 @name="Bob Bobertson", @score=77>, #<Student:0x0055e86b9002c8 @name="George Carlson", @score=83>]
- room_one.average # => 86.66666666666667
- room_two = Classroom.new "Math"
- room_two.add_student(Student.new("William Shatner", 55)) # => [#<Student:0x0055e86b8f81e0 @name="William Shatner", @score=55>]
- room_two.add_student(Student.new("Leonard Nimoy", 97)) # => [#<Student:0x0055e86b8f81e0 @name="William Shatner", @score=55>, #<Student:0x0055e86b8f7678 @name="Leonard Nimoy", @score=97>]
- room_two.average # => 76.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement