Kurt Euler wrote in post #1156967:
Hi. Newbie here, with an even “stoopider” question than Ken’s.
I’ve been readings David A. Black’s fine “Well Grounded Rubyist” book.
Just reading now the chapter on classes. What I’m finding missing so far
are examples of why one would normally need more than one instance of a
(user created) class. Perhaps this comes from my procedural programming
(BASIC, back in 1970s high school). But I can’t see yet the general
kinds of things you can do with multiple class instances that you can’t
do programmatically, say, with a database. You send a ruby query to it,
read the response in to an object, and then work with it. OK so maybe
there’s more than one hit in the querie. Do you need to read each into
an array of objects in order to work with it?
It can make things simpler. You could think of a record as an object,
and deal with the objects this way:
person1 = [1, “John”, 50]
person2 = [2, “Sally”, 50]
id = person1[0]
name = person1[1]
hours_worked = person1[2]
pay = 15 * hours_worked
puts “#{name}, whose id is #{id}, worked #{hours_worked} hours, earning
$#{pay}.”
–output:–
John, whose id is 1, worked 50 hours, earning $750.
But that code is somewhat cryptic. Ruby does have facilities for
turning db records into hashes, enabling you to do this:
person1 = {
id: 1,
name: “John”,
hours: 50,
}
person2 = {
id: 2,
name: “Sally”,
hours: 50,
}
pay = 15 * person1[:hours]
puts “#{person1[:name]}, whose id is #{person1[:id]}, worked
#{person1[:hours]} hours, earning $#{pay}.”
–output:–
John, whose id is 1, worked 50 hours, earning $750.
On the other hand, an instance of a class is a bundle
containing both data and methods, enabling you to do things
like this:
class Person
attr_accessor :id, :name, :hours
def initialize(id, name, hours)
self.id = id #calls accessor rather than directly setting @id
self.name = name
self.hours = hours
end
def pay(rate)
rate * self.hours
end
end
person1 = Person.new(1, “John”, 50)
person2 = Person.new(2, “Sally”, 50)
puts “#{person1.name}, whose id is #{person1.id}, worked
#{person1.hours} hours, earning $#{person1.pay(15)}.”
–output:–
John, whose id is 1, worked 50 hours, earning $750.
And as the methods get more numerous and complex, it can
be more convenient to have the methods bundled with the
object, for instance when calling a method that takes
a Person as an argument.
Also note, the accessor methods can be used to validate the entered
data:
class Person
attr_accessor :id, :hours
attr_reader :name
def initialize(id, name, hours)
self.id = id #calls accessor rather than directly setting @id
self.name = name
self.hours = hours
end
def pay(rate)
pay = rate * self.hours
pay_str = sprintf("%.2f", pay)
currency = “$”
“#{currency}#{pay_str}”
end
def name=(str)
@name = str.capitalize
end
end
person1 = Person.new(1, “john”, 50)
person2 = Person.new(2, “Sally”, 50)
puts “#{person1.name}, whose id is #{person1.id}, worked
#{person1.hours} hours, earning #{person1.pay(15)}.”
–output:–
John, whose id is 1, worked 50 hours, earning $750.00.
However, maybe a better answer is: you don’t get to know
“why classes” yet. Think of classes as a trick you are
learning. You don’t necessarily have to know why the trick
is useful, but if you learn the trick, then someday you
may find some use for it. When programming, it’s always
better to have alternatives.
Also consider the fact, that ruby hashes and arrays are instances of a
class. Think about how you would implement them without using classes.
Is it as convenient?
In any case, you can write lots of useful programs with ruby
without defining your own classes–so don’t worry too much
about it.