Matthias B. wrote:
I am now trying to grasp what a class isand what is is for. I understand
that there a bunch of different classes, but how does that help me?
In your code you use a lot of objects, right? Like 1 is an Integer
object,
“hello” is a String object, /\d+/ is a Regexp object, [] is an Array
object,
2…3 is a Range object (made out of two Integer objects) and so on.
You will have noticed that those objects all have a different set of
methods:
You can do (2…3).each or [1,3,5].each, but you can’t do 4.each or
/la/.each.
You can do “I’m a string”.length, but you can’t do 3.length.
You can do 5.times, but you can’t do “hello”.times.
And it makes sense that it works that way, right? Cause what would the
length
of an Integer be? Or what would it mean to execute a block of code
“hello”
times?
As you can see, certain methods only make sense when used with a certain
kind
of object. But how does Ruby know which objects are supposed to have
which
methods? It know because of classes:
Every object is an instance of a class. “hello” is an instance of class
String, 5 is an instance of class Integer (Fixnum actually, but let’s
not
care about the difference at this point), 3…4 is an instance of class
Range
and so on. Those classes describe what properties and methods their
instances
have. “hello” has the methods length, gsub, tr and so on because they
are
defined as methods of String. 2…5 and [“a”,“b”,“c”] have the method
each
because in the class Range as well as in the class Array there is a
method
called each. And so on.
But what can you do with classes? Well, you can use those classes by
using
their instances. But you’re already doing that. Even when you do 3 + 5
you’re
using two instances of a class (3 and 5 of class Integer) and one method
of
that class (the method +).
So what else can you do with classes? For starters you can extend the
existing
classes. Let’s say you have a method that “censors” a string:
def censor(string)
string.gsub(/./, “x”)
end
You can use it like this: censor(“hello world”), but now you’re thinking
that
it would be much more fun if you could use it like this: “hello
world”.censor
cause after all: all the other methods working with strings are used
that way
too. So here’s how you’d do that:
class String
def censor()
self.gsub(/./, “x”)
end
end
Now you can type “hello”.censor and get back “xxxxx” (how very useful,
isn’t
it). You will have noticed that where we previously said string.gsub we
now
said self.gsub. Why’s that? That’s because the parameter string doesn’t
exist
anymore. We want to call the method like mystring.censor() without any
paramether. The method should work with the string that’s in front of
the dot
(also called the receiver of the method) and not with any parameter. So
how
do we access the receiver? By using self. Inside a method definition
self
will point to the object that the method has been called on. So when you
do “hello”.censor, self is “hello” and if you do “bla”.censor, self is
bla.
Actually we wouldn’t have even needed to use self in there: If you call
a
method and you don’t specify a receiver (i.e. you write foo() instead of
self.foo() ), the receiver is assumed to be self. So gsub(…) would be
the
same as self.gsub(…).
So that’s how you can extend existing classes. But sometimes that’s not
enough. I mean think about what kind of objects does ruby have? Strings,
numbers, ranges of numbers, ranges of strings,… BORING! You’re a
people
person, you can’t be expected to sit in the basement all day and only
work
with numbers and strings. So ruby clearly needs a way to use people in
your
program. So what we do is we create a class called Person that describes
what
properties a person has and what he/she can do (what methods he/she
has). So
that we can then use Person objects (I know you usually shouldn’t think
of a
person as an object, but here it’s okay) in our code. Here’s how to:
First you decide what properties a person should have. For now let’s
keep it
small and only let him/her have a name.
class Person
def initialize(firstname, surname)
@fname = firstname
@sname = surname
end
def name()
“#{@fname} #{surname}”
end
def firstname()
@fname
end
def surname()
@sname
end
end
So how do you use this class? Like this:
my_person = Person.new(“John”, “Smith”)
new is a method that can be used on classes. It creates an instance of
this
class and then calls a method called initialize on it (that’s why we
defined
such a method in our class). So now our initialize method gets called
with
the parameters firstname and surname. All it does with those two is
store
them: the value of firstname gets stored in @fname and the value of
surname
in @sname. Variables starting with an @-sign are so called instance
variables. They’re properties of an object. If a method sets an instance
variable to some value, all methods that get called on the same object
can
now see this value when they access that variable.
Other than initialize there are three other methods: firstname, surname
and
name. firstname and surname are boring. All they do is return the value
of
the instance variable @fname or @sname respectively. name is a bit
different.
It uses @fname and @sname to create the full name and then returns that.
Of
course you can do things far more advanced than this with classes, but
this
should give you something to start with.
HTH,
Sebastian