1class Machine 2 attr_accessor :filename, :machine_data 3 4 def initialize(filename, machine_data) 5 @filename = filename 6 @machine_data = machine_data 7 end 8 9 def open_file 10 @file = File.open(@filename) 11 end 12 13 def parse_data_each_line 14 @file.read.split("\n") 15 end 16 17 def remodeling_data 18 @machine_data.each do |element| 19 end 20 end 21end
In the above case even though attr_accessor is defined the user is not using it effectively.
The programmer is using instance variables @filename and @machine_data directly.
In an instance of a class the instance variables are available globally in the object. Anywhere in the object any instance method can get hold of any instance variable by just using @name_of_variable.
This behavior of instance variables makes instance variables like a global constant. Any instance method can read it and any instance method can update it.
In the above class notice that method open_file is creating an instance variable @file. And method parse_data is accessing that instance variable.
If we just look at those two methods then they are using @file as a global constant. This is not a good way to write object oriented programs.
Object oriented programming is about accessing the data the right way. And the right way in this case would be by using attr_reader, attr_writer or attr_accessor.
Let's try to fix the above code. First let's see how @file_name and @machine_data are being used. Both of these instance variables are being read. No method is setting value to to it. So there is no need to have attr_accessor. Let's change that to attr_reader and change the code so that @file_name and @machine_data is not directly used.
1class Machine 2 attr_reader :filename, :machine_data 3 4 def initialize(filename, machine_data) 5 @filename = filename 6 @machine_data = machine_data 7 end 8 9 def open_file 10 @file = File.open(filename) 11 end 12 13 def parse_data_each_line 14 @file.read.split("\n") 15 end 16 17 def remodeling_data 18 machine_data.each do |element| 19 end 20 end 21end
Now let's fix how @file is being used. The method open_file is writing to this instance variable and method parse_data is reading this instance variable. So we should use attr_accessor for this.
1class Machine 2 attr_reader :filename, :machine_data 3 attr_accessor :file 4 5 def initialize(filename, machine_data) 6 @filename = filename 7 @machine_data = machine_data 8 end 9 10 def open_file 11 self.file = File.open(filename) 12 end 13 14 def parse_data_each_line 15 file.read.split("\n") 16 end 17 18 def remodeling_data 19 machine_data.each do |element| 20 end 21 end 22end
Please note that in method open_file we need to use self.file =. If we use only file = then Ruby will create a local variable called file.