Slides
Classes and Instances
Ref. WGR Chapter 3, Organizing objects with classes
The Cookie Metaphor
- a class is a cookie cutter
 - an instance is a cookie
 - memory is cookie dough
 - state is frosting
 - users are hungry!
 
Example Class
class Cookie
  def sweeten(more_chips = 10)
    @chips ||= 0    # lazy initialization
    @chips += more_chips
  end
  def yummy?
    @chips and @chips >= 20
  end
end
Creating and Using Objects
- 
To create an object, call the new method on its class
cookie = Cookie.new - 
To call a method an object, use the dot operator
cookie.sweeten(50) cookie.yummy? #=> true 
Constructors
- To instantiate an object, call the new method on its class
 - The new method then calls initialize
 
class Cookie
  def initialize
    @chips = 0
  end
end
cookie = Cookie.new  # *not* Cookie.initialize!
Active vs. Lazy Initialization
Active initialization (inside the constructor) leads to simpler code elsewhere in the object, since other methods can assume the instance variables are ready to roll.
Active Initialization
class Cookie
  def initialize
    @chips = 0    # active initialization
  end
  def sweeten(more_chips = 10)
    @chips += more_chips
  end
  def yummy?
    @chips >= 20
  end
end
Lazy Initialization
class Cookie
  def sweeten(more_chips = 10)
    @chips ||= 0    # lazy initialization
    @chips += more_chips
  end
  def yummy?
    @chips and      # defensive coding
      @chips >= 20
  end
end
What does new do?
- allocates memory for the instance
 - calls initialize on the new instance
 - returns a pointer to the instance
 
So by the time assignment (=) happens, the object has been constructed and initialized.
So a constructor is your one big chance to initialize everything before anyone else gets a pointer to it.
Instance methods
- defined inside the class
 - instance methods are shared among all instances
 - same behavior, but different data
 
class Cookie
  def bake
    @temp = 350
  end
end
Instance variables
- represent object state
 - names start with an 
@ - only visible inside the object
- i.e. when 
selfis that object 
 - i.e. when 
 
Getter and setter methods
class Person
  def age=(years_old)
    @age = years_old
  end
  def age
    @age
  end
end
alice = Person.new
alice.age= 17
alice.age #=> 17
alice.@age #=> SyntaxError
Ruby's setter sugar
alice.age = 17
is the same as
alice.age=(17)
- Technically, it's not an assignment, it's a method call
 - ...but it looks like an assignment!
- that's called "syntactic sugar" since it makes the syntax sweeter
 
 
The setter gotcha
- Inside an object, you can't call that object's setter methods directly
 
class Person
  def age=(years_old)
    @age = years_old
  end
  def bar_mitzvah!
    age = 13   # oops
  end
end
- Why not?
- Because "
age = 13" looks like a local variable assignment, which takes precedence - It eclipses the setter method!
 - Syntax ambiguity! Oh noes!
 
 - Because "
 
The setter gotcha solved
- Solution: use "
self.age"- that forces it to be a method call
 
 - or 
@age- that's a direct instance variable reference
 
 
class Person
  def age=(years_old)
    @age = years_old
  end
  def bar_mitzvah!
    @age = 13
  end
  def bat_mitzvah!
    self.age = 13
  end
end
Attributes
- An attribute is a property with named getter and/or setter methods
 - Usually corresponds to an instance variable
 
Attribute Shortcuts
aka "macros"
class Thing
  attr_reader :age    #  def age; @age; end
  attr_writer :age    #  def age=(x); @age = x; end
  attr_accessor :age  # both of the above
end
Constructor plus Attributes
class Person
  attr_accessor :age
  def initialize
    @age = 20
  end
end
alice = Person.new
alice.age #=> 20
Attribute Shortcuts (cont.)
- Can also take multiple arguments
 
class Thing
  attr_accessor :foo, :bar
end
thing = Thing.new
=> #<Thing:0x007fe008897278>
>> thing.methods
=> [:foo, :foo=, :bar, :bar=,
Attribute Shortcuts (cont.)
- Wait a second!
 - Q: Where are 
attr_readeret al. defined? - A: They are class methods of 
Object - A: Or maybe they're instance methods of 
ClassorModule; I'm not sure. 
Attribute Shortcuts (cont.)
- Sadly, 
attr_accessoris misnamed - "accessor" means 
reader, butattr_accessormakes a reader and a writer - Should have been called just 
attribute 
Lazy Initialization with Or-Equals
class Cookie
  def chips
    @chips ||= 10
  end
end
Query methods
class Person
  def child?
    @age < 18
  end
end
alice.age = 16
alice.child? #=> true
Note: query methods return a boolean by convention only
Bang methods
class Person
  def birthday!
    @age = @age + 1
  end
end
- "
!" is pronounced "bang" - usually means "watch out" or "destructive" or "side effect"
- could also mean "may raise an exception"
 - no real rule, so watch out
 
 - normally there's a non-bang equivalent
 - in ActiveRecord, "
!" means: raise exception if failure 
A Poorly-Encapsulated Object
class BadStudent
  attr_accessor :first_name, :last_name
end
joe = BadStudent.new
joe.first_name = "Joe"
joe.last_name = "Blow"
puts joe.first_name + " " + joe.last_name
A Well-Encapsulated Object
class GoodStudent
  def initialize first_name, last_name
    @first_name, @last_name = first_name, last_name
  end
  def full_name
    "#{@first_name} #{@last_name}"
  end
end
jane = GoodStudent.new("Jane", "Brain")
puts jane.full_name
A Well-Encapsulated Object (cont)
- Why is this well-encapsulated?
- initial state established by constructor
 - internal state used by methods, not exposed by getters
 - other objects do not have direct access to its internal state
 - if requirements change, code only changes in one place
- e.g. adding a middle name
 
 
 - Both shorter and safer than a poorly-encapsulated object
 
Labs
Outline
- Classes and Instances
 - The Cookie Metaphor
 - Example Class
 - Creating and Using Objects
 - Constructors
 - Active vs. Lazy Initialization
 - Active Initialization
 - Lazy Initialization
 - What does `new` do?
 - Instance methods
 - Instance variables
 - Getter and setter methods
 - Ruby's setter sugar
 - The setter gotcha
 - The setter gotcha solved
 - Attributes
 - Attribute Shortcuts
 - Constructor plus Attributes
 - Attribute Shortcuts (cont.)
 - Attribute Shortcuts (cont.)
 - Attribute Shortcuts (cont.)
 - Lazy Initialization with Or-Equals
 - Query methods
 - Bang methods
 - A Poorly-Encapsulated Object
 - A Well-Encapsulated Object
 - A Well-Encapsulated Object (cont)
 - Labs