Advertisement
nanenj

STP Facebook Post

Nov 5th, 2017
138
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 6.80 KB | None | 0 0
  1. Hi Marty,
  2.  
  3. Looking at your code, I notice first off that you've got some unnecessary lines.
  4.  
  5. attr_reader
  6. attr_writer
  7. attr_accessor
  8.  
  9. You don't need all 3 of these.
  10.  
  11. Let's take a quick look at what this does.
  12.  
  13. class Student
  14.  attr_reader :name
  15.  
  16.  def initialize(name)
  17.    @name = name
  18.  end
  19. end
  20.  
  21. 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.
  22.  
  23. So, if we continue the above code with...
  24.  
  25. student_one = Student.new("Marty Carr")  # => #<Student:0x00555615cec618 @name="Marty Carr">
  26. puts student_one.name                    # >> Marty Carr
  27.  
  28. However, right now if you were to try...
  29.  
  30. student_one.name = "Bob Bobertson"       # ~> -:13:in `<main>': undefined method `name=' for #<Student:0x0055c608151d18 @name="Marty Carr"> (NoMethodError)
  31.  
  32. 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.
  33.  
  34. Let's alter the above sample code a tiny bit, and make it an attr_writer instead.
  35.  
  36. class Student
  37.   attr_writer :name
  38.  
  39.   def initialize(name)
  40.     @name = name
  41.   end
  42. end
  43.  
  44. student_one = Student.new("Marty Carr") # => #<Student:0x0055697acd9a18 @name="Marty Carr">
  45. student_one.name = "Bob Bobertson"      # => "Bob Bobertson"
  46. puts student_one.name                   # ~> -:12:in `<main>': undefined method `name' for #<Student:0x005563ba9bfcf8 @name="Bob Bobertson"> (NoMethodError)
  47.  
  48. 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...
  49.  
  50. class Student
  51.  attr_writer :name
  52.  
  53.  def initialize(name)
  54.    @name = name
  55.  end
  56.  
  57.  def name
  58.    @name
  59.  end
  60. end
  61.  
  62. student_one = Student.new("Marty Carr") # => #<Student:0x005579784ff758 @name="Marty Carr">
  63. student_one.name = "Bob Bobertson"      # => "Bob Bobertson"
  64. puts student_one.name                   # >> Bob Bobertson
  65.  
  66. So, lastly, there's a helper for if you need/want/desire both functionalities, and that's the attr_accessor helper.
  67.  
  68. class Student
  69.  attr_accessor :name
  70.  
  71.  def initialize(name)
  72.    @name = name
  73.  end
  74. end
  75.  
  76. student_one = Student.new("Marty Carr") # => #<Student:0x005586035ebe18 @name="Marty Carr">
  77.  
  78. student_one.name = "Bob Bobertson"      # => "Bob Bobertson"
  79. puts student_one.name                   # >> Bob Bobertson
  80.  
  81. See how that works?
  82.  
  83. 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.
  84.  
  85. class Student
  86.   attr_accessor :name, :score
  87.  
  88.   def initialize(name, score)
  89.     @name = name
  90.     @score = score
  91.   end
  92. end
  93.  
  94. students = []
  95.  
  96. students << Student.new("Marty Carr", 100)    # => [#<Student:0x005560a72fb900 @name="Marty Carr", @score=100>]
  97. students << Student.new("Bob Bobertson", 77)  # => [#<Student:0x005560a72fb900 @name="Marty Carr", @score=100>, #<Student:0x005560a72fb310 @name="Bob Bobertson", @score=77>]
  98. 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>]
  99.  
  100. At this point, we've got three students, and we want an average of their scores.
  101.  
  102. We can do...
  103.  
  104. class Student
  105.  attr_accessor :name, :score
  106.  
  107.  def initialize(name, score)
  108.    @name = name
  109.    @score = score
  110.  end
  111. end
  112.  
  113. students = []
  114.  
  115. students << Student.new("Marty Carr", 100)    # => [#<Student:0x0055a0fba24bc0 @name="Marty Carr", @score=100>]
  116. students << Student.new("Bob Bobertson", 77)  # => [#<Student:0x0055a0fba24bc0 @name="Marty Carr", @score=100>, #<Student:0x0055a0fba244b8 @name="Bob Bobertson", @score=77>]
  117. 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>]
  118.  
  119. number_of_students = students.count           # => 3
  120. students.map { |student| student.score }.reduce(0) { |sum, x| sum + x / number_of_students.to_f }
  121.  
  122. # => 86.66666666666667
  123.  
  124. To get a better picture of the above, I'll break it apart.
  125.  
  126. scores = students.map { |student| student.score } # => [100, 77, 83]
  127. total = scores.reduce(0) { |sum, x| sum + x }     # => 260
  128. total / number_of_students                        # => 86
  129. total / number_of_students.to_f                   # => 86.66666666666667
  130.  
  131. Pretty cool, huh?
  132.  
  133. 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.
  134.  
  135. class Classroom
  136.   attr_accessor :students, :name
  137.  
  138.   def initialize(name)
  139.     @students = []
  140.     @name = name
  141.   end
  142.  
  143.   def add_student(student)
  144.     @students << student
  145.   end
  146.  
  147.   def average
  148.     @students.map { |student| student.score }.reduce(0) { |sum, x| sum + x / @students.count.to_f }
  149.   end
  150. end
  151.  
  152. class Student
  153.   attr_accessor :name, :score
  154.  
  155.   def initialize(name, score)
  156.     @name = name
  157.     @score = score
  158.   end
  159. end
  160.  
  161. a = Student.new("Marty Carr", 100)    # => #<Student:0x0055e86b908130 @name="Marty Carr", @score=100>
  162. b = Student.new("Bob Bobertson", 77)  # => #<Student:0x0055e86b902118 @name="Bob Bobertson", @score=77>
  163. c = Student.new("George Carlson", 83) # => #<Student:0x0055e86b9002c8 @name="George Carlson", @score=83>
  164.  
  165. room_one = Classroom.new "Science"
  166.  
  167. room_one.add_student(a)               # => [#<Student:0x0055e86b908130 @name="Marty Carr", @score=100>]
  168. room_one.add_student(b)               # => [#<Student:0x0055e86b908130 @name="Marty Carr", @score=100>, #<Student:0x0055e86b902118 @name="Bob Bobertson", @score=77>]
  169. 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>]
  170.  
  171. room_one.average                      # => 86.66666666666667
  172.  
  173. room_two = Classroom.new "Math"
  174.  
  175. room_two.add_student(Student.new("William Shatner", 55)) # => [#<Student:0x0055e86b8f81e0 @name="William Shatner", @score=55>]
  176. room_two.add_student(Student.new("Leonard Nimoy", 97))   # => [#<Student:0x0055e86b8f81e0 @name="William Shatner", @score=55>, #<Student:0x0055e86b8f7678 @name="Leonard Nimoy", @score=97>]
  177.  
  178. room_two.average                      # => 76.0
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement