Programming C, C++, Java, PHP, Ruby, Turing, VB
Computer Science Canada 
Programming C, C++, Java, PHP, Ruby, Turing, VB  

Username:   Password: 
 RegisterRegister   
 [Ruby-tut] Objects... objects everywhere!
Index -> Programming, Ruby -> Ruby Tutorials
View previous topic Printable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic
Author Message
wtd




PostPosted: Fri Jul 02, 2004 8:18 pm   Post subject: [Ruby-tut] Objects... objects everywhere!

So, knowing how to do simple input and output, test conditions, define methods, and construct loops, what's next?

At this point it becomes possible to understand classes and objects and all of that wonderful object-oriented stuff. Why bother? That's a good question, and the simple but correct answer is that it's because objects are at the heart of Ruby, and to really understand Ruby you need to understand classes and objects.

Of course, that's only the answer to "why bother if I care in the slightest about Ruby?" The answer to that question can only be realized by using it, and even then it's more a subconscious realization. You don't so much realize how much Ruby is doing for you as much as you come to appreciate the tedious little odds and ends that you aren't doing.

Classes are sort of a blueprint for objects. They define how an object is laid out and what it can do. Instance variables are the pieces of information stored inside an object, and methods are what an object can do.

In Ruby, all instance variables are private. They cannot be directly accessed by other objects. Also by default, methods in Ruby classes are public. They can be made private or protected, but the same cannot be done for instance variables.

The reasoning behind this is that methods define the interface of an object. Instance variables allow the object to maintain a certain state. Since other objects don't care what instance variables an object has, they are not predefined, and can be freely added, so long as the changes don't change what the object looks like from the outside.

Ruby makes this approach feel more natural by not requiring parentheses. It can feel like you're accessing an instance variable, but the reality is that you'd be accessing a method which in turn returns the instance variable.

As a simple example, let's create a simple class which defines a name.

code:
class Name
   def initialize(first, last)
      @first, @last = first, last
   end
end


Here "initialize" is somewhat like a constructor in other languages, except that it's a normal method which can be used at any time. It just happens that it's a method called by the "new" method of the class itself.

But I digress...

A "class method"? Remember, everything in Ruby is an object, and this extends even to classes. As a result classes can have variables and methods. The "new" class method simply takes a variable number of arguments and then passes those onto the initialize method which does the work of setting up the initial condition of the object. Of course "new" also handles memory allocation and such, but there's no need to worry about that.

To pass on those arguments Ruby has another use for the * operator that's used for "slurping" up extra arguments to a method.

code:
def foo(*extra_args)
   extra_args.each { |arg| puts arg }
end


In this simple example, "extra_args" becomes an array holding all of the additional arguments. Now in Ruby, by default, an array is just a single object, and normally passing it to a method asan argument it's treated as a single argument. We can, however, force it to be evaluated in the context of a list. For example, we'll pass an array into foo as a single argument, and as a list.

code:
foo([1, 2, 3, 4])

foo(*[1, 2, 3, 4])


The latter is equivalent to:

code:
foo(1, 2, 3, 4)


That said...

Back to our regularly scheduled tutorial

code:
@first, @last = first, last


The @ symbols look rather odd, but are a simple way of designating instance variables, as opposed to local variables. Class variables are indentified by @@ and global variables are prefixed with a $.

Consider instance variables as "global" to all of a particular object's methods. Class variables are essentially global to all objects of a given class. Global variables are global to... well... everything.

The use of the = operator looks a bit odd here, but this is standard Ruby behavior. The first variable on the right is assigned to the first variable/value on the left and so forth. If there are more variables/values on the right than the left, the excess will be ignored.

For instance, in the following, 3 is ignored.

code:
a, b = 1, 2, 3


However, we could use the same slurping behavior seen in methods here.

code:
a, *b = 1, 2, 3


Here "a" becomes 1, but "b" is now an array with 2 and 3.

The other possibility is that there aren't enough values on the right hand side.

code:
a, b, c = 1, 2


In this case "a" is 1, "b" is 2, and "c" is "nil".

Back on topic again

So now we can create a Name object with a first and last name. To create a new name object is an easy task.

code:
bobs_name = Name.new("Bob", "Smith")


Now, as I mentioned earlier, the instance variables are always private, so we can't get at them at this stage. We'll likely want that access, though, so let's modify the class to add accessor methods for the two variables.

code:
class Name
   def initialize(first, last)
      @first, @last = first, last
   end
   
   def first
      @first
   end
   
   def last
      @last
   end
end


Pretty easy, wasn't it? Fortunately Ruby can make it easier. For automatically creating such simple accessor methods there are the attr* keywords. Since we're only reading the values of the first and last names, and not trying to change them we'll just use "attr_reader".

code:
class Name
   attr_reader :first, :last

   def initialize(first, last)
      @first, @last = first, last
   end
end


Of course, now we want to output the name.

code:
bobs_name = Name.new("Bob", "Smith")

puts "#{bobs_name.first} #{bobs_name.last}"


But maybe we should have a method which returns a string with the names in that format. And maybe one that returns something like "Smith, Bob". The former we expect to be more common, so we'll alias "to_s" to that method so that puts automatically uses that format.

code:
class Name
   attr_reader :first, :last

   def initialize(first, last)
      @first, @last = first, last
   end
   
   def full_name
      "#{first} #{last}"
   end
   
   alias :to_s :full_name
   
   def reverse_full_name
      "#{last}, #{first}"
   end
end


code:
bobs_name = Name.new("Bob", "Smith")

puts bobs_name
puts bobs_name.reverse_full_name


One last quirky thing

Classes in Ruby, unlike most other languages, are not ever really finished. If you should decide that you want to add something later on, you can easily do so. For instance, were we to want a method that switches the first and last names in a Name object, we could easily do so. Why we would want to is another story entirely.

Assume the previous definition of the Name class.

code:
class Name
   def switch_names!
      @first, @last = @last, @first
   end
end


That's pretty much it for the simple stuff.
Sponsor
Sponsor
Sponsor
sponsor
TokenHerbz




PostPosted: Sat Mar 25, 2006 8:23 pm   Post subject: Re: [Ruby-tut] Objects... objects everywhere!

wtd wrote:

That's pretty much it for the simple stuff.


I'd hate to see the hard stuff :S
rdrake




PostPosted: Sun Mar 26, 2006 9:41 pm   Post subject: Re: [Ruby-tut] Objects... objects everywhere!

TokenHerbz wrote:
I'd hate to see the hard stuff :S
Remember that if you have any questions, just ask here, the IRC channel, or wherever wtd/Minsc/myself/Hikaru79/others are. We'll be happy to help you out.
wtd




PostPosted: Mon Mar 27, 2006 1:27 pm   Post subject: (No subject)

Ask as soon as you run into problems. It really makes offering help hard when someone asks for help with "chapter 8" and only reveals sometime later that they didn't make it through "chapter 3."

Smile
Display posts from previous:   
   Index -> Programming, Ruby -> Ruby Tutorials
View previous topic Tell A FriendPrintable versionDownload TopicRate TopicSubscribe to this topicPrivate MessagesRefresh page View next topic

Page 1 of 1  [ 4 Posts ]
Jump to:   


Style:  
Search: