So what's the big deal about object oriented programming?
There are multiple approaches to writing code. Functional, procedural, and object-oriented are three of the most common. If you are learning Ruby, you need to know about object oriented programming. The previous posts all included examples of procedural code. Procedural code is code that runs line by line and does one task at a time, each task building on the other. This is fine for smaller programs, like the ones in previous posts. However, it can quickly become unwieldy if you are trying to work on larger projects. For example, say you were to write a program to make a cat meow and a dog bark. All of the code in this, written procedurally, would know about the other code. So the cat might know the .bark method, and the dog might know the .meow method. When everything knows about each other, there is a lot of room for cascading effects as you adjust one line of code.
Does the dog need to know how to meow? No. It doesn't. In fact, a dog being able to meow might even break the dog all together. This is where object oriented programming becomes useful. Object oriented program is arranged as a collection of objects (a Cat object, and a Dog object, for example), rather than as a list of tasks that need to be performed. In procedural programming, all mechanics are dependent on each other. It is a collection of parts that are independently dysfunctional. Procedural programming does not support partial testing, and is difficult to make updates to the code, and nearly impossible to scale it. In object oriented programming, however, the application is a sum of it's parts. Each individual object is testable on its own, and each object is customizable. This makes updates and scaling easy to accomplish.
Some of the core concepts of object oriented programming come down to roles, interface, and encapsulation. In Object oriented programming, each object has it's own role. This is that objects one and only job. It does not need to know about other objects or their jobs. A dog does not need to know that the .meow method exists, nor that the cat can use it. This is a separation of concerns. When things don't know about other things, there is less likelihood of something breaking. The interface is a set of known objects and methods. All objects expose a public interface to communicate with each other. Encapsulation means that objects are self-contained. Each object should be like a black box, it should not expose it's internal workings to other objects, nor should it be worried about other objects internal workings.
So, in Ruby, how does one make objects? Use objects? Write in object oriented ways? Everything in Ruby is an object. But one of the best ways to write object oriented code is by uses classes.
The way you create a class is similar to creating a method.
class Cat end
That's it! Classes are always capitalized. Within classes you can create methods to use on the class. Classes are like blueprints. For example, you have a class Cat. You have the basic structure of a cat: it meows, it purrs, and it sleeps. But you might at some point need a cat with a louder purr, so you can take the cat class and do some separate customization on it.
When you create a class, you should always initialize it. Initializing is setting the defaults for the class, or the characteristics it will start out with.
class Cat def initialize puts "meow end end
If you would like to create a new instance (aka instatiating) of a class you can assign it to a variable and use the .new method.
nikki = Cat.new
You can also pass a class arguments and assign it private instance variables.
class Cat def initialize(name, breed) @name = name @breed = breed end end
didi = Cat.new("Didi", "calico")
You can also assign "getter" and "setter" methods, which allow you to assign and retrieve information about a specific instance of the class.
class Cat def initialize(name, breed) @name = name @breed = breed end def name #getter return @name end def name=(name) #setter @name = name.capitalize end end
Remember that part about customization? It's really easy to do by using sub-classes. A sub-class inherets the traits from it's parent class. You can do this by doing the following:
class Didi < Cat end
The '<' means "extend." So you are extending the properties of the Cat class into the Didi class. You can then put in customized instance variables, or modify the behavior of the Cat class specifically for Didi.