OOP

  • Fully object oriented (like Smalltalk); all data in Ruby is an object (i.e. The number 1 is an instance of class Fixnum)
  • Flexible OO support (you can add methods to a class or instance during runtime)
  • No multiple inheritance (by design)
  • A class can contain any number of mixins (partial class definitions), which provides some of the advantages of multiple inheritance
  • Every object has a unique object id
  • As with Smalltalk, method calls are expressed/described as messages; the message contains the method name and any parameters needed; the text before the dot is the receiver, and the text after the dot is the method to invoke
  • Attributes - data members for which accessor methods (getters) and attribute-setting methods (serving the purpose of setters) have been defined

Instance variables

class Garden
@watered = false
...
end

Instance methods

  • Parentheses don't appear to be required for calling parameter-less methods
  • For a method with parameters, it's almost always best to use parentheses (to avoid precedence confusion); in a simple case, like puts "Hello", it may be reasonable to omit the parentheses
  • The value returned by a Ruby method is the value of the last expression evaluated (the return command is not required)
class Garden
...
def water(minutes)
...
return true
end
end

garden = Garden.new("lettuce", "apple")
garden.water(10)

Method access

  • public - accessible by any class
  • protected - accessible within the class and by any derived class (useful for allowing objects to access data members of other objects of the same class)
  • private - accessible only within the class
  • Methods are public by default (except for initialize, which is always private)
class Garden
# Methods defined here are public by default
...

# Private methods
private
...

# Protected methods
protected
...

# Public methods
public
...
end
class Garden
# Methods
...

public :method1, :method2
protected :method3
private :method4
end

Accessor methods

  • Getters / inspectors
class Garden
...
def vegetable
@vegetable
end
def fruit
@fruit
end
end

# Shorthand notation
class Garden
...
attr_reader :vegetable, :fruit
end

garden = Garden.new("lettuce", "apple")
puts garden.vegetable
puts garden.fruit

Attribute-setting methods

  • Setters / mutators
class Garden
...
def vegetable=(newVegetable)
@vegetable = newVegetable
end
def fruit=(newFruit)
@fruit = newFruit
end
end

# Shorthand notation
class Garden
...
attr_writer :vegetable, :fruit
end

garden = Garden.new("lettuce", "apple")
garden.vegetable = "spinach"
garden.fruit = "orange"

Class constants

class Garden
MAX_GARDENS = 10
...
end

Class variables

class Garden
@@numGardens = 0
...
end

Class methods

class Garden
...
def Garden.tooManyGardens
return (&&numGardens > MAX_GARDENS)
end
end

print "Too many gardens" if Garden.tooManyGardens

Constructors

  • The initialize method is automatically called when the object is created
class Garden
def initialize(vegetable, fruit)
@vegetable = vegetable
@fruit = fruit
end

def to_s
"#{@vegetable} #{@fruit}"
end
end

garden = Garden.new("lettuce", "apple")
puts garden

Inheritance

class LargeGarden < Garden
def initialize(vegetable, fruit, flower)
super(vegetable, fruit)
@flower = flower
end

def to_s
super + " #{@flower}"
end
end

largeGarden = LargeGarden.new("lettuce", "apple", "rose")
puts largeGarden