OO programming
==============

Smalltalk: an Example OO Language
=================================

The following notes introduce OO using the Smalltalk language. After programming in LISP, you may be very happy with Smalltak- often the code has no brackets!

Until 5 years ago, I would have said that Smalltalk is was an historical language (something to be studied by ancient scholars). Now, maybe not (see all the interest in Seaside and GNU Smalltalk).

Anyway, we don't study it to program in it. Rather, we use it to define an abstract spec of what an OO language should look like. From that, we will then audit GOLD- an OO language written in 100 lines of LISP.

History
=======

Smalltalk was developed at Xerox Parc in the 1970s by a team that included Alan Kay, Dan Ingalls, Adele Goldberg, Ted Kaehler, Scott Wallace, and others. Alan Kay is famous for saying

     The best way to predict the future is to invent it.

He wasn't kidding. Smalltalk is famous for creating the bitmapped multi-windowed mouse-driven environment that inspired Steve Jobs to create the first Macintosh. Up until the iPhone/iPad, the Smalltalk interfaces were the dominant influence on our vision of a computer. Consider the following images from the Sept 1977 Scientific American Article, "Microelectronics and the Personal Computer" pp. 230-244, by Alan Kay.  Note the definition of some core ideas:

     "Windows," display frames within the larger display screen, enable the user to organize and edit information at several layers of refinement. Once the windows are created they overlap on the screen like sheets of paper. Images with various degrees of symbolic content can be display simultaneously.

But What are Objects?
=====================

Lets take a moment to review the seven main buzzwords of OO:

  * Classes

  * Instances

  * Attributes

  * Operations

  * Inheritance

  * Classification

  * Encapsulation

  * Polymorphism

Classes make instances and, usually, distinction is as follows:

  * Design time: classes

  * Runtime: instances

(By the way, here's something really cool. Everything in Smalltalk is an instance, including classes:

  * The class of the instance "3" is "Integer".

  * And "Integer" is an instance of the class "Class".

  * And "Class" is an instance of the class "MetaClass".

  * And the buck stops here: "MetaClass" is an instance of the class "MetaClass".)

Instances have attributes, operations, identity, and associations.

  * Attributes (state, data)

  * Operations (behavior, function, code), which Smalltalk calls methods. For example, an "Account" object might comment on its own status:
     ! Account methods !
     inTheRed
     	^balance < 0
     !!

  * Identity (uniqueness, memory location)

  * Associations (who you talk too).

Instances can use inheritance, classification, encapsulation and polymorpishm:

  * Inheritance (ask your father). For example: old mean jump the same way young men do (just not as often).
     Person                (has "dob", does "walk")
          Male             (does "jump")
               OldMale     (does "dance", and calls jump a little)
               YoungMale   (does "dance", and calls jump a lot)
          Female           (does "dance" and "jump")

     (Aside: do Males have a "dob"? How do "OldMale"s jump?)

  * Classification (factory, stencil)

       * Classes store our knowledge of instances.

       * For example, they can tune instance creation. Here are "Account" class methods that return specially tuned "Account" instances (don't worry about the syntax details, we'll get back to those later.
          ! Account class methods !
          bigAccount
          	^self new minBalance: 1000000
          !
          smallAccount
          	^self new maxBalance: 20000
          !!

  * Encapsulation (border guards)

       * Hide what you can, reveal only what you need.

  * Polymorphism (polly wanna cracker and don't care how you do it)

       * E.g. "Circle", "Triangle" and "Square" all draw themselves different ways but they all might respond to the message "draw". E.g. All our "Person"s, above, respond to "dance", but all do it differently.

       * So polymorphism means same interface, different internal behavior.

For Example
-----------

For example, you could be modeled as a network of associations between instances of the class "Body", "Arm", and "Leg":

  * "Body" is a container instance containing 2 "Arms", 2 "Legs", and one "Head".

  * "Body" has core attributes "age", "spouse", "address", as well as other attributes to store pointers to the "Arms", "Legs", and "Head".

  * "Body" has operations: jump, talk, dance etc.

Note classic newbie OO mistake: associations is not inheritance;

  * Just because "CarYards" have "Cars", does not mean that "CarYards" isa "Car";

  * Just because dogs can access cats, does not mean dog isa cat (but it might be true that they share some super class; e.g. "Dog" isa "Pet" and "Cat" isa "Pet").

So it is not true that "Arm" isa "Body". Rather, "Body" uses "Arm".

For another example, "Fraction" contains two integers: the "Numerator" and the "Denominator". "Fraction" is not a sub-class of "Integer"- but it does use Integers.

Lesson: a working OO system is a conversation between networks of objects.

Talking from Sub to Super
=========================

Let's say that we've got an Account class:

Object subclass: #Account
          instanceVariableNames: 'balance'
          classVariableNames: ''
          poolDictionaries: ''
          category: nil !

!Account methods !
spend: amount
     balance := balance - amount
!
deposit: amount
     balance := balance + amount
!
init
      balance := 0
!!
This last init method initializes the hidden variable "balance" (actually called an instance variable ) to zero, which makes sense for an account balances.

We can create the Savings class as a subclass of Account. It holds money, just like an Account, but has an additional property that we will model: it is paid interest based on its balance.
Account subclass: #Savings
   instanceVariableNames: 'interest'
   classVariableNames: ''
   poolDictionaries: ''
   category: nil !

The instance variable "interest" will accumulate interest paid. Thus, in addition to the "spend:" and "deposit:" messages which we inherit from our parent, Account, we will need to define a method to add in interest deposits, and a way to clear the interest variable (which we would do yearly, after we have paid taxes). We need to define a method for allocating a new account - we need to make sure that the interest field starts at 0.
!Savings methods !
init
     interest := 0.
     ^super init
!!
Can you guess what super init does? Its the sub-class method calling the parent. It is like saying "do my own initializations for my own variables (interest) then go away and do whatever you need to do to initialize my inherited properties.

While this is a trivial example, such definitions-via-extension are very useful when dealing with (say) complex interface classes where super-classes have some intricate initialization sequence. Subclasses need not understand that initialization sequence, all they need to do is to call daddy and ask him to run that complex code.

One of our challenges for GOLD is to handle such super-class calls.

Singletons
----------

As an aside (and this is a concept we will return too in later lectures) is that one thing you want to with initialization control is handle singletons; i.e. classes for which there should only be one instance, and provide a global point of access to it.

Why singletons? Well, often, a system only needs to create one instance of a class, and that instance will be accessed throughout the program. Examples would include objects needed for logging, communication, database access, etc. You could pass such an instance from method to method, or assign it to each object in the system. However, this adds a lot of unnecessary complexity.

Singletons are most appropriate for services that do not change their nature based on their invocation context. A singleton can be created at startup based on context or be reset for larger scale state transitions

Simply put: singletons make it easy to compose a program from different components.  Singletons do not create unnatural interdependencies made by passing a context object around, where every piece of code will bind to everything in the context object. Singletons stand alone.

Examples:

  * One "cut" buffer shared by all instances of a text editor (so you can cut, copy, paste between any text editing sessions).

  * One random number stream, shared by all parts of the program.

  * One logging stream, that everyone writes too.

  * (Esoteric) Languages that initialize all their globals as single instances of some class. e.g. in Smalltalk:

       * "true", "false", "nil"

       * are singletons of the classes "True", "False" and "UndefinedObject", respectively (aside: so, unlike in LISP, "nil" is an object with customizable properties).

How to do it in Smalltalk?

Step 1: add a ClassVariable to a class.

Account subclass: #Database
   instanceVariableNames: ''
   classVariableNames: 'CurrentDatabaseConnection'
   poolDictionaries: ''
   category: nil !!

Step 2: change the new method that only returns the same instance, over and over again.
!Database class methods!
new
	CurrentDatabaseConnection isNil ifTrue:[
		CurrentDatabaseConnection := super new].
	^CurrentDatabaseConnection
!!

That's it! Now, whenever we create a "new" instance of this class, we just use the same one over and over again.

Note that there is a much much much more elegant way to create Singletons (see the uber-elegant way Io does it (http://media.pragprog.com/titles/btlang/lo.pdf), on p72-74-  which we'll explore in later lectures).

What Makes OO Exceptional: Distributed Control
==============================================

In the above example, we could specialize instance creation by writing a new "new" method, that runs just for one exceptional class (DataBase's singleton method).

That's OO- everything is exceptional. Polymorphism means that general procedures that can specialized for particular objects without mucking up the centralized controller.

To illustate that point, we  take a look at how procedural control can be defined in an OO system.

Blocks
------

Before doing that, we have to know about "Blocks" which is Smalltalk's version of lambda bodies.
|x y z|
x := [3 > 7].
y := [:a | a > 7].
z := [:a :b | a > b].

x value.              "Returns true"
y value: 10           "Returns false"
z value: 10 value: 20 "Returns false"

Distributed if-then-else
------------------------

All control in Smalltalk is based on blocks. The message
3 > 7 ifTrue: [Transcript printOn: 'yes'].
The way this works is that: 3 > 7 evaluates to some subclass of Boolean:

  * In Smalltalk, true is the single instance of the class True and false is the single instance of the class False.

  * So the message ifTrue: with the argument [Transcript printOn: 'yes'] is handled by either a method of the class True or False.

The code for those methods is shown below:
! True methods !
ifTrue: trueBlock
	^trueBlock value "We are true -- evaluate trueBlock"
!!

! False methods !
ifTrue: trueBlock
	^nil "We are false -- do nothing"
!!
Note that this is an example of pure OO: the object-oriented message system is being enlisted to replace procedural if-then-else.

Distributed Enumeration Control
-------------------------------

Using Blocks, trick, we can also implement for-loops. Here's the equivalent of LISP's dotimes macro:
! Number methods !
to: stop do: aBlock
        | i |
        i := self.
        [i <= stop] whileTrue: [ "whileTrue is a built-in"
                aBlock value: i.
                i := i + 1
        ]
        ^stop
!!
For example:
1 to: 5 do: [:i|
   Transcript printOn: i]
And here the equivalent of LISP's dolist macro:
! SequenceableCollection methods !
do: aBlock
    1 to: (self size) do: [:i |
           aBlock value: (self at: i)]
!!
For example:
'this is a string' do: [:char|
   Transcript printOn: char]

Why Bother?
-----------

Now consider the advantages of such distributed control structures:

  * If, in "C", you wanted to define a new kind of for-loop, you'd need to change the "C" compiler and optimizer. Not a task for the feint-hearted.

  * On the other hand, in Smalltalk, it is just a matter of writing just another method.

Which means, extending the language to bury away common processing constructs inside higher-level commands is much easier than in "C".

So there is a whole industry in building domain-specific languages. For example, here's a state machine language, written in Smalltalk. Each machine contains states (e.g. #start, #run) which are connected by transitions (e.g. if happiness < 2 then go to #run).
! Factory methods !
worksIn: factory
    factory
       machine: (self new: 'party boy');
       go: #start   to: #run     then:  [The machine talks: 0];
       go: #run     to: #oddHaHa then:  [The machine talks: 1];
       go: #run     to: #even    then:  [The machine talks: 2];
       go: #oddHaHa to: #oddHaHa then:  [The machine
                                            drinks;
                                            talks: 3];
       go: #oddHaHa to: #run     if:    [The machine happiness < 2 ]
                                 then:  [The machine
                                            talks: 4;
                                            talks: 'Too drunk to stay awake.'];
       go: #even    to: #run;
       go: #run     to: #endF    if:    [App random next > 0.9]
                                 then:  [The machine
                                            talks: 5;
                                            talks: 'that is all folks'.
                                         The yourself oo.
                                         The state oo.
                                         The next oo.
                                         The machine oo.
                                         The factory oo].
!!
For more on this language, see the agent-ready (http://code.google.com/p/agent-ready/source/browse/trunk/lib/) code base.

For more on domain-specific languages see my notes on that topic (http://courses.ece.ubc.ca/571f/lectures.html).