Exploring Languages with Interpreters
and Functional Programming

Chapter 3
Object-Based Paradigms

H. Conrad Cunningham

28 August 2018

Copyright (C) 2018, H. Conrad Cunningham

Acknowledgements: I created these slides in Fall to accompany Chapter 3, Object-Based Paradigms, of the book Exploring Languages with Interpreters and Functional Programming.

Browser Advisory: The HTML version of this document may require use of a browser that supports the display of MathML. A good choice as of August 2018 is a recent version of Firefox from Mozilla.

Object-Based Paradigms

Lecture Goals

Assumptions

Key idea: Real world can be accurately described as collection of interacting objects

  1. Easier to understand complex systems as interacting objects
  2. Behaviors of real world objects stable over time
  3. Kinds of real world objects stable over time
  4. Changes tend to be localized to a few objects
1 \Longrightarrow simplifies development
2 & 3 \Longrightarrow enable reuse, prototyping, incremental development
4 \Longrightarrow supports design for change

Object-Oriented Approach

Object Model

  1. Objects (abstract data structures)

  2. Classes (abstract data types)

  3. Inheritance (hierarchical relationships among abstract data types)

  4. Subtype polymorphism

Dynamic binding? Consider implementation technique for polymorphism rather than characteristic

Model: Objects

Essential characteristics

Important but non-essential characteristics

First-Class Citizens

Objects usually first-class entities

[a] State

Collection of information held by object:

Attributes – components of state

[b] Operations

[c] Identity

Can distinguish between two distinct objects

[d] Encapsulation

Encapsulation – private features not directly accessible outside

E.g. Java private instance variables and method encapsulated

Object-based languages without true encapsulation

[e] Independent Lifecycle

Independent lifecycle:

Object exists independently from program unit that created it (independent lifetime)

Classroom Sim Objects

Object-Based Languages

Language object-based if supports objects as feature

Object-based languages:

Ada, Modula, Clu, C++, Java, Scala, C#, Smalltalk, and Python 3

Not inherently object-based:

Pascal (without module extensions), Algol, Fortran, C

Model: Classes (1)

Class – template or factory for creating objects

Model: Classes (2)

Class description includes definitions of:

Classroom Sim Classes

Class-based Languages

Class-based language

Class-based languages:

Clu, C++, Java, Scala, C#, Smalltalk, Ruby, Ada 95:

Not class-based:

Ada 83, Modula, Lua, core JavaScript,

Classes and Types

Model: Inheritance (1)

Goal: Encourage reuse of design and code

Class C inherits from class P if C’s objects form a subset of P’s objects.

Classroom Sim Inheritance (1)

    // Java or Scala
    class Furniture  // extends cosmic root class for references
    {   ...   }      // (java.lang.Object, scala.AnyRef)

    class Desk extends Furniture
    {   ...   }  // implement "move" op

    class StudentDesk extends Desk
    {   ...   }  // share "move" from Desk

    class ComputerDesk extends Desk
    {   ...   } // share "move" from Desk

Classroom Sim Inheritance (2)

Figure 3-1: Classroom Simulation Inheritance Hierarchy

Classroom Sim Inheritance (3)

Figure 3-2: Classroom Simulation with Multiple Inheritance

Classroom Sim Inheritance (4)

Problems with multiple inheritance in StudentDesk

Solutions complex:

Classroom Sim Inheritance (5)

    // Java
    interface Location3D
    {   ...   } // variable defs, method signatures

    interface HumanHolder
    {   ...   }

    interface Seat extends Location3D, HumanHolder
    {   ...   } // default method defs in newer Java

    interface BookHolder
    {   ...   }

    interface BookBasket extends Location3D, BookHolder
    {   ...   }

    class StudentDesk extends Desk implements Seat, BookBasket
    {   ...   }

Classroom Sim Inheritance (6)

Figure 3-3: Classroom Simulation with Interfaces

Model: Subtype Polymorphism (1)

Polymorphism – “many forms”:
hide different implementations behind common interface
Subtype polymorphism:
associate operation call with appropriate implementation in class hierarchy

also called polymorphism by inheritance, inclusion polymorphism, subtyping

Usually at runtime – dynamic binding to nearest implementation

Model: Subtype Polymorphism (2)

    class Desk extends Furniture
    {   ...
        public void move(...)
        ...
    }

    class StudentDesk extends Desk
    {   ...
        // no move(...) operation here
        ...
    }

    class ComputerDesk extends Desk
    {   ...
        // no move(...) operation here
        ...
    }

Model: Subtype Polymorphism (3)

    class Desk extends Furniture 
    {   ...
        public void move(...)
        ...
    }

    class StudentDesk extends Desk
    {   ...
        // no move(...) operation here
        ...
    }

    class ComputerDesk extends Desk
    {   ... // what about cords?
        public void move(...)
        ...
    }

Python 3 Class (1)

    class CountingOO:                  # (1)

        def __init__(self,c,m):        # (2,3)
            self.count = c             # (4)
            self.maxc  = m

        def has_more(self,c,m):        # (5)
            return c <= m 

        def adv(self):                 # (6)
            self.count = self.count + 1
    
        def counter(self):             # (7)
            while self.has_more(self.count,self.maxc):
                print(f'{self.count}') # (8)
                self.adv()

Python 3 Class (2)

    class CountingOO:                  # (1)

        def __init__(self,c,m):        # (2,3)
            self.count = c             # (4)
            self.maxc  = m
  1. Inherits from cosmic root class object by default – otherwise parents in parenthesis after class name

  2. Uses initializer __init__, not really constructor

  3. Lists receiver object as first parameter – convention self

  4. Has instance variables count, maxc; access with self.

Python 3 Class (3)

        def has_more(self,c,m):        # (5)
            return c <= m 

        def adv(self):                 # (6)
            self.count = self.count + 1
    
        def counter(self):             # (7)
            while self.has_more(self.count,self.maxc):
                print(f'{self.count}') # (8)
                self.adv()
  1. Boolean function has_more()hook method in Template Method design pattern

  2. Procedure adv() sets self.counthook method

Python 3 Class (4)

        def counter(self):             # (7)
            while self.has_more(self.count,self.maxc):
                print(f'{self.count}') # (8)
                self.adv()
  1. Procedure counter() – primary public interface to object – template method in Template Method design pattern

  2. Expression f'{self.count}' – Python 3.7 interpolated string

Python 3 Class (5)

    class CountingOO:                  # (1)

        def __init__(self,c,m):        # (2,3)
            self.count = c             # (4)
            self.maxc  = m

        def has_more(self,c,m):        # (5)
            return c <= m 

        def adv(self):                 # (6)
            self.count = self.count + 1
    
        def counter(self):             # (7)
            while self.has_more(self.count,self.maxc):
                print(f'{self.count}') # (8)
                self.adv()

Using Python 3 Class

    ctr = CountingOO(0,10)
    ctr.counter()

Gives output

    0
    1
    2
    ...
    10

Extending Python 3 Class (1)

    class Times2(CountingOO):    # inherits from CountingOO

        def has_more(self,c,m):  # overrides
            return c != 0 and abs(c) <= abs(m)

        def adv(self):           # overrides
            self.count = self.count * 2

Extending Python 3 Class (2)

    ctr2 = Times2(-1,10)
    ctr2.counter()

Gives output

    -1
    -2
    -4
    -8

Prototype-based Paradigm

Prototype-based language

Prototype:

Classes vs. Prototypes

Student Who Plays Chess (1)

Using classes

Student Who Plays Chess (2)

Using prototype objects

Evolution of Tony

Can evolve object Tony object using prototype cloning

Delegation

May delegate to prototype object rather then copy it completely

Prototypes Into Classes

Prototype and delegation

Prototype-Based Languages

Lua Design Principles

Dynamically typed, multiparadigm language with design principles:

Lua Implementation Requirements

Why?

Lua Usage

Separate Mechanism from Policy

Examples:

Tables Are Objects

Method Call

Reference to function closure in table obj (expression) at key method

    obj.method(obj, other_arguments)

Represented by syntactic sugar

    obj:method(other_arguments) 

Receiver obj called parameter self in body

Delegation

Metatable mechanism with metamethod __index:

Lua Prototype Module (1)

    -- File CountingPB.lua 
    local CountingPB = {count = 1, maxc = 0} -- (1)
    
    function CountingPB:new(mixin)           -- (2)
       mixin = mixin or {}                   -- (5)
       local obj = { __index = self }        -- (4)
       for k, v in pairs(mixin) do           -- (5)
          if k ~= "__index" then
             obj[k] = v
          end
       end
       return setmetatable(obj,obj)          -- (6,7)
    end

    function CountingPB:has_more(c,m)        -- (2)
       return c <= m
    end
    
    function CountingPB:adv()                -- (2)
       self.count = self.count + 1
    end
    
    function CountingPB:counter()            -- (2)
       while self:has_more(self.count,self.maxc) do
          print(self.count)
          self:adv()
        end
    end
    
    return CountingPB                        -- (3)

Lua Prototype Module (2)

    -- File CountingPB.lua 
    local CountingPB = {count = 1, maxc = 0} -- (1)
       ...
    function CountingPB:new(mixin)           -- (2)
       ...
    function CountingPB:has_more(c,m)        -- (2) 
       ...
    function CountingPB:adv()                -- (2)
       ...
    function CountingPB:counter()            -- (2)
       ...    
    return CountingPB                        -- (3)
  1. Create module CountingPB as table with default values (prototype obj)

  2. Define methods new(), has_more, etc

  3. Return CountingPB from require call

Lua Prototype Module (3)

    function CountingPB:new(mixin)           -- (2)
       mixin = mixin or {}                   -- (5)
       local obj = { __index = self }        -- (4)
       for k, v in pairs(mixin) do           -- (5)
          if k ~= "__index" then
             obj[k] = v
          end
       end
       return setmetatable(obj,obj)          -- (6,7)
    end

Method new (arbitrary name) constructs clones

  1. Creates as table with __index set to receiver

  2. Copies mixin entries into clone, adds or changes

  3. Sets clone’s metatable to clone itself

  4. Returns clone object – module convention

Lua Prototype Module (4)

On access to undefined key

Prototype delegation functionality

Lua Prototype Module (5)

    -- File CountingPB.lua 
    local CountingPB = {count = 1, maxc = 0} -- (1)
    
    function CountingPB:new(mixin)           -- (2)
       mixin = mixin or {}                   -- (5)
       local obj = { __index = self }        -- (4)
       for k, v in pairs(mixin) do           -- (5)
          if k ~= "__index" then
             obj[k] = v
          end
       end
       return setmetatable(obj,obj)          -- (6,7)
    end

    function CountingPB:has_more(c,m)        -- (2)
       return c <= m
    end

    function CountingPB:adv()                -- (2)
       self.count = self.count + 1
    end

    function CountingPB:counter()            -- (2)
       while self:has_more(self.count,self.maxc) do
          print(self.count)
          self:adv()
        end
    end
    
    return CountingPB                        -- (3)

Using Lua Prototype Module (1)

Load CountngPB.lua module, create object, call counter

    local CountingPB = require "CountingPB"

    x = CountingPB:new({count = 0, maxc = 10})
    x:counter()

Gives output

    0
    1
    2
    ...
    10

Using Lua Prototype Module (2)

Create clone of object x

    y = x:new({count = 10, maxc = 15})
    y:counter()

Give output

    10
    11
    12
    13
    14
    15

Using Lua Prototype Module (3)

    z = y:new( { maxc = 400,
                 has_more = function (self,c,m)
                    return c ~= 0 and math.abs(c) <= math.abs(m)
                 end,
                 adv = function(self)
                    self.count = self.count * 2
                 end,
                 bye = function(self) print(self.msg) end 
                 msg = "Good-Bye!" } )
    z:counter()
    z:bye()

Gives output

    16
    32
    64
    128
    256
    Good-Bye!

OO versus PB

Key Ideas

Source Code