Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruby-the-VM vs. Ruby-the-Language #17

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 94 additions & 28 deletions lessons/01_classes.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,35 @@
# Object Orientation: Classes, Instances, and Methods

## Overview
Rubyists always say "in Ruby, everything is an object." From a beginner's perspective, that's quite confusing. Objects know information, called attributes, and they can do actions, called methods. A more useful statement than "everything is an object" could be "everything has attributes and methods."

For an example of an object, think about you as a human being. You have attributes like height, weight, and eye color. You have methods like "walk", "run", "wash dishes", and "daydream." Different kinds of objects have different attributes and methods. In the next sections we’ll look at a few specific kinds of objects common in Ruby.

A class is an abstract idea. It defines what all objects of that type can know and do. Think of the chair you’re sitting in. It’s not an abstract chair, it is an actual chair. We’d call this actual chair an instance - it is a realization of the idea chair. It has measurable attributes like height, color, weight. The class chair, on the other hand, has an abstract weight, color, and size – we can’t determine them ahead of time.

We'll start with something that *could* be a physical object, like a Product. First let's define a couple things.
Rubyists always say "in Ruby, everything is an object", but from a beginner's
perspective, that's quite confusing. What they mean is that inside the Ruby
Virtual Machine (VM) -- the ruby program that executes your code -- every
concept it knows about is what we call an object; each object knows specific
information about itself (attributes) and can do actions (methods). A more
useful statement could be "in a Ruby Program, everything has both attributes
and methods – even attributes and methods have attributes and methods."

As a developer, you will interact with your Ruby *Programs* (full of objects,
of course) using the Ruby *Language*. This is an important distinction, since
one is a collection of concepts, and the other is the *language* used to
describe and interact with the objects *using* those concepts.

For an example of an *object*, think about you as a human being. You have
attributes like height, weight, and eye color. You have methods like "walk",
"run", "wash dishes", and "daydream." Different kinds of objects have different
attributes and methods. In the next sections we’ll look at a few specific kinds
of objects common in Ruby.

A *class* is an abstract idea. It defines what all objects of that type can know
and do. Think of the chair you’re sitting in. It’s not an abstract chair, it is
an actual chair. We’d call this actual chair an instance - it is a realization
of the idea chair. It has measurable attributes like height, color, weight. The
class chair, on the other hand, has an abstract weight, color, and size – we
can’t determine them ahead of time.

We'll start with something that *could* be a physical object, like a Product.
First let's define a couple things, in the Ruby *Language*:

``` ruby
class Product
Expand All @@ -22,23 +44,39 @@ end

Here is a list of the Objects involved in this class:

- Product (Class)
- Product.new (returns an instance of the product class)
- Product.new.name => "Fleece Wolf Blanket" (an instance of the class String)
- Product.new.weight_in_ounces => 12 (an instance of the class Integer)

The things that are not Objects are

- `def`
- `end`
- The actual method name (i.e. `weight_in_ounces`)
- `Product` (Class - an abstract concept)
- `Product.new` (returns a new instance of the product class.)
- `"Fleece Wolf Blanket"` (a *string-literal*, an instance of the class String.
It is called literal because in the Ruby Language it *exactly* represents the
Ruby Object that it will create)
- `12` (an *integer-literal* representation of the number twelve, an instance of
the class Integer)

There are also a number of words in that block of code that *don't* directly
represent an object on their own, but together help to build our little Ruby
universe:

- `class` (a ruby *keyword* that opens up a `Class`)
- `def` (a ruby *keyword* that starts defining a method)
- `name` and `weight_in_ounces` (since these words immediately follow the
keyword `def`, they are method names; used elsewhere they might mean
something else -- in fact, we will use these same words later to *call* the
methods that are being defined.)
- `end` (a ruby *keyword* that finishes the current definition)

### Return Value
When we say that "every method returns an object", we bring up a very important concept.

Executing code is transactional, meaning that we give the computer code to execute, and the computer gives us a response. The response the computer gives is ALWAYS an object. Methods can be separated by `.`, which just tells the computer to execute the next word on the object that the last word returned.
When we say that "every method returns an object", we bring up a very important
concept.

Executing code is transactional, meaning that we give the computer code to
execute, and the computer gives us a response. The response the computer gives
for a Ruby method is ALWAYS an object. Methods can be separated by `.`, which
just tells the computer to execute the next word on the object that the last
word returned, a concept known as "chaining".

Let's imagine that the computer is a person and we're asking them to process this request for us.
Let's imagine that the computer is a person and we're asking them to process
this request for us, one line at a time.

``` ruby
product = Product.new
Expand All @@ -63,6 +101,8 @@ Let's walk through that line-by-line:
and remember that as the variable `product` in case you wanna
use it later.

You're done? OK. I'll show you a representation of that object.

``` ruby
product = Product.new
# => <Product:0x000001009ea6c8>
Expand All @@ -80,6 +120,9 @@ product = Product.new
Checking, checking. Okay, got it. It's `"Fleece Wolf Blanket"`.
So there you go: `"Fleece Wolf Blanket"`.

You're done? OK. I'll show you a representation of that string
object.

``` ruby
product.name
# => "Fleece Wolf Blanket"
Expand All @@ -102,6 +145,9 @@ product.name
go ahead and finally return `"TEKNALB FLOW ECEELF"` for
you to do what you'd like with.

You're done? OK. I'll show you a representation of that string
object.

``` ruby
product.name.reverse.upcase
# => "TEKNALB FLOW ECEELF"
Expand All @@ -119,12 +165,18 @@ product.name.reverse.upcase
you `nil`. This is an Object, but you can't do much with it.
I wouldn't recommend trying to call any more methods on it.

You're done? OK. I'll show you a representation of the nil object.

``` ruby
product.destroy
# => nil
```

In this example, for every word we type, the computer is returning an object. In the case of `product.name.reverse.upcase`, the computer is given four methods and is returning four objects. Even though we will only see the final result that `upcase` gives us, the computer is computing the first three methods all the same. So according the computer, this is what happened
In this example, for every word we type, the computer is returning an object.
In the case of `product.name.reverse.upcase`, the computer is given four methods
and is returning four objects. Even though we will only see the final result
that `upcase` gives us, the computer is computing the first three methods all
the same. So according the computer, this is what happened

- Receives `product`, returns `<Product @name>`
- Receives `<Product @name>`.name, returns `"Fleece Wolf Blanket"`
Expand All @@ -134,23 +186,37 @@ In this example, for every word we type, the computer is returning an object. In
The computer handles things one word at a time.

## Frequently-Used Objects
In the last section, we said *everything is an object*. This is a confusing concept at first, but let's go over a couple of examples to highlight that point.
In the last section, we said *everything is an object*. This is a confusing
concept at first, but let's go over a couple of examples to highlight that
point.

We're already familiar with strings and integers. Strings and integers are objects, too! Try `"hello".class` in IRB. What do you get?
We're already familiar with strings and integers. Strings and integers are
objects, too! Try `"hello".class` in IRB. What do you get?

Just like our Product class, which defined the abstract idea of a product, there's a String class that defines the abstract idea of string. The same is true for `2.class` (Fixnum) and `2.3.class` (Float).
Just like our Product class, which defined the abstract idea of a product,
there's a String class that defines the abstract idea of string. The same is
true for `2.class` (Fixnum) and `2.3.class` (Float).

Even classes have classes! Try `"hello.class.class"`!

Commonly-used classes have pre-defined methods baked in - that's how Ruby works from the inside out. To see what methods are available on any object, just call `.methods`. Try it with `"hello".methods`.
Commonly-used classes have pre-defined methods baked in - that's how Ruby works
from the inside out. To see what methods are available on any object, just call
`.methods`. Try it with `"hello".methods`.

Just to go further down the rabbit hole, the response of `"hello.methods"` is even an object, so you can call `.class` on it. Turns out that it is an Array (which is an object type we'll get to very soon).
Just to go further down the rabbit hole, the response of `"hello.methods"` is
even an object, so you can call `.class` on it. Turns out that it is an Array
(which is an object type we'll get to very soon).

We can use Array's predefined methods on `"hello".methods`, like `.count`. `"hello".methods.count` will give us the number of methods you can call on any string. How many are there?
We can use Array's predefined methods on `"hello".methods`, like `.count`.
`"hello".methods.count` will give us the number of methods you can call on any
string. How many are there?

## Optional Lesson: More About Methods
Can't get enough methods? Check out Chapter 6 of Learn to Program. It'll go over some common (and not-so-common) methods for some of our favorite types of objects: integers and strings.
Can't get enough methods? Check out Chapter 6 of Learn to Program. It'll go
over some common (and not-so-common) methods for some of our favorite types of
objects: integers and strings.

## Homework
* Work through Chapters 7, 8, 12, and 13 of Learn to Program on your own.
* Read Chapter 2 (stuff you know) and Chapter 3 (stuff you know, plus some new ideas) in Beginning Ruby.
* Read Chapter 2 (stuff you know) and Chapter 3 (stuff you know, plus some
new ideas) in Beginning Ruby.