Skip to content

Instantly share code, notes, and snippets.

@dariusf
Last active October 21, 2015 02:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dariusf/163dbd5475153e474e47 to your computer and use it in GitHub Desktop.
Save dariusf/163dbd5475153e474e47 to your computer and use it in GitHub Desktop.

We were introduced to OOP this week. While it may seem very complex, at heart it's still about the same notions of data and operations on data.

As JediScript has a rather complicated OOP system with many moving parts, it's important to distinguish the ideas from the implementation.

Ideas

  • State and behaviour: Objects comprise state and behaviour. Programs are no longer structured around just functions, but around a central object which specific functions operate on. Computation usually involves updating the state of that central object over time.

  • Aggregation: As with functions, we can compose objects, building large objects out of smaller ones.

  • Classification: Common characteristics in objects can be factored out, leading to the idea that objects can be put into classes, each with their own kinds of state and behaviour.

  • Specialisation: We want to describe concepts as more specific versions of other concepts, so parts of our programs can be reused. The type of specialisation we use is classical inheritance.

  • Encapsulation: The notion that interactions with an object should be confined to a specific interface, and that the parts which should not be accessed should be hidden. Helps us better manage complexity. JediScript has no encapsulation by default, but is flexible enough that we can implement it ourselves.

Implementation

Object literals {}

  • 'classless' objects
  • properties can be easily added and changed
  • a["property"] === a.property (keys are strings)

new

  • creates an instance of a class
  • turns a function into a constructor
  • sets the __proto__ property of the object to the prototype of the constructor

Constructor

  • initialises an instance of a class
  • usually also stands-in for the class, for example in is_instance_of
  • may call a superclass constructor
  • is a function: any function can serve as a constructor
  • is also an object with a prototype property

this

  • the current object
  • like a hidden function parameter which can be set in various ways
  • nothing special; can be simulated with an explicit parameter
  • rules are actually very simple:
    • obj.method(...): this is set to obj in the body of method
    • method.call(obj, ...): this is set to obj in the body of method
    • new Constructor(): this is set the new object that is created in the constructor
    • otherwise: undefined

Method invocation

  • calls a function with the object it is invoked with set to this

call

  • explicitly sets this in the body of a function and relays the remaining arguments to it
  • used to call superclass constructor for inherited properties
  • used to call superclass methods

Inherits

  • sets up the prototype chain between classes
  • more specifically, the __proto__ property of the subclass constructor's prototype is set to the prototype of the superclass constructor

prototype

  • a property of a constructor function
  • usually contains methods of an object which are shared across all instances
  • the __proto__ property of objects created with the constructor is set to this

__proto__

  • a property of an object created with a constructor
  • can also be explicitly set in an object literal
  • properties that can't be found on the object are searched for here (prototype chain)

is_instance_of

  • checks if an object is an instance of a class (represented by the constructor)
  • internally searches the prototype chain to see if the prototype of the constructor appears somewhere in it

bind

  • like call, but returns a function with this bound instead

How the way we've written programs has changed

Pure/functional

Bank accounts support two operations, deposit and withdraw.

function make_bank_account(initial) {
    return pair("bank account", initial);
}

var get_balance = tail;

function withdraw(bank_account, amount) {
    return make_bank_account(get_balance(bank_account) - amount);
}

function deposit(bank_account, amount) {
    return make_bank_account(get_balance(bank_account) + amount);
}

var b = make_bank_account(10);
var b2 = withdraw(b, 4);
get_balance(b2); // 6
var b3 = deposit(b2, 10);
get_balance(b3); // 16
  • After each operation, we end up with a new bank account, just like how we ended up with a new list, curve, and jedisound.
  • We create new things instead of changing things.

State

var set_balance = set_tail;

function withdraw(bank_account, amount) {
    return set_balance(bank_account, get_balance(bank_account) - amount);
}

function deposit(bank_account, amount) {
    return set_balance(bank_account, get_balance(bank_account) + amount);
}

var b = make_bank_account(10);
withdraw(b, 4);
get_balance(b); // 6
deposit(b, 10);
get_balance(b); // 16
  • Now, we change things. We mutate the pair that we use to represent a bank account and give it a new value. This changes its state.

OOP

We've always written programs by defining some data (lists, curves, jedisounds, bank accounts), then creating operations over the data (append, connect_rigidly, consecutively, withdraw). OOP is really just about organising these two things together.

function BankAccount(initial) {
    this.amount = initial;
}

BankAccount.prototype.get_balance = function () {
    return this.amount;
};

BankAccount.prototype.deposit = function (amount) {
    this.amount = this.amount + amount;
};

BankAccount.prototype.withdraw = function (amount) {
    this.amount = this.amount - amount;
};

var b = new BankAccount(10);
b.withdraw(4);
b.get_balance(); // 6
b.deposit(10);
b.get_balance(); // 16
  • Same as the stateful version, just with special syntax
  • There are new features (prototypes, inheritance), but exactly the same fundamental ideas: data, and operations over data.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment