Edward Byne
Friday 24 April 2015
"Object-oriented design requires that you shift from thinking of the world as a collection of predefined procedures to modeling the world as a series of messages that pass between objects."
Sandi Metz, Practical Object-Oriented Design in Ruby (2013)
"In a world of objects, new arrangements of behaviour emerge naturally. You don't have to explicitly write code for the spouse_steps_on_cat procedure, all you need is a spouse object that takes steps and a cat that does not like being stepped on. Put these objects into a room together and unanticipated combinations of behaviour will appear."
Sandi Metz, Practical Object-Oriented Design in Ruby (2013)
Java
JavaScript
Self
Scheme
Syntax
Functions
Prototypes
Largely an amalgamation of three different languages:
greeting = String.new("Hello, World!")
greeting = "Hello, World!"
OR:
greeting.length
# - > 13
greeting.upcase
# - > "HELLO, WORLD!"
We can create our own classes:
class Dog
attr_reader :name
def initialize(name)
@name = name
@tired = false
end
def bark
"Woof!"
end
def walk
@tired = true
end
def sleep
@tired = false
end
def tired?
@tired
end
end
dog = Dog.new("Henry")
dog.bark
# - > "Woof!"
dog.tired?
# - > false
dog.walk
dog.tired?
# - > true
A class can be derived from another class:
class Beagle < Dog
def howl
"Awoooooo!"
end
end
beagle = Beagle.new("Henry")
beagle.bark
# - > "Woof!"
beagle.howl
# - > "Awoooooo!"
Beagle.superclass
# - > "Dog"
A class can contain other classes:
class Tail
def wag
"Wag wag!"
end
end
class Dog
attr_reader :name
def initialize(name)
@name = name
@tired = false
@tail = Tail.new
end
def wag_tail
@tail.wag
end
end
dog = Dog.new("Henry")
dog.wag_tail
# - > "Wag wag!"
var dog = {
name: "Henry",
isTired: false,
walk: function() {
this.isTired = true;
},
sleep: function() {
this.isTired = false;
}
};
dog.name;
// - > "Henry"
dog.isTired;
// - > false
dog.walk();
dog.isTired;
// - > true
var empty = {};
empty.toString;
// - > function toString() { ... }
Object.getPrototypeOf(empty);
// -> Object {}
"The problem with object-oriented languages is they've all got this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."
Joe Armstrong, interviewed in Coders at Work
var Dog = function(name) {
this.name = name;
};
dog = new Dog("Henry");
// - > { name: "Henry" }
Dog.prototype;
// - > {}
var Dog = function(name) {
this.name = name;
this.isTired = false;
};
Dog.prototype.bark = function() {
return "Woof!";
};
Dog.prototype.walk = function() {
this.isTired = true;
};
Dog.prototype.sleep = function() {
this.isTired = false;
};
dog = new Dog("Henry");
dog.name;
// - > "Henry"
dog.bark();
// - > "Woof!"
Prototypes can inherit from other prototypes:
var Beagle = function(name) {
this.name = name;
};
Beagle.prototype = new Dog();
beagle = new Beagle("Henry");
beagle.bark();
// - > "Woof!"
var Tail = function() {};
Tail.prototype.wag = function() {
return "Wag wag!"
};
var Dog = function(name) {
this.name = name;
this.tail = new Tail();
};
Dog.prototype.wagTail = function() {
return this.tail.wag();
};
dog = new Dog("Henry");
dog.wagTail();
// - > "Wag wag!"
And composition is also possible:
Object.prototype
Function.prototype
Array.prototype
Dog.prototype
Beagle.prototype
1. Inheritance is optional in prototypal languages
var dog = Object.create(null);
Object.getPrototypeOf(dog);
// - > null
2. Prototypes may help to avoid complex taxonomies
2. Prototypes may help to avoid complex taxonomies (continued)
"JavaScript is conflicted about its prototypal nature."
"The pseudoclassical form can provide comfort to programmers who are unfamiliar with JavaScript, but it also hides the true nature of the language. The classically inspired notation can induce programmers to compose hierarchies that are unnecessarily deep and complicated."
Douglas Crockford, JavaScript: The Good Parts, 2008
3. Prototypal objects inherit state as well as behaviour
4. Prototype changes have retroactive heredity
dog = new Dog("Henry");
dog.bark();
// - > "Woof!"
Dog.prototype.bark = function() {
return "Wau!";
};
dog.bark();
// - > "Wau!"
5. Prototypal objects are dynamic
dog = new Dog("Henry");
dog.bark();
// - > "Woof!"
dog.bark = function() {
return "Wau!";
};
dog.bark();
// - > "Wau!"
dog.isHungry = true;
dog.isHungry
// - > true
6. Prototypal objects do not generally have private data
var dog = function(name) {
var name = name;
return {
bark: function() {
return "Woof!";
},
readNameTag: function() {
return name;
}
};
}
henry = dog("Henry")
henry.name;
// - > undefined
henry.readNameTag();
// - > "Henry"
class Dog {
constructor(name) {
this.name = name;
this.isTired = false;
}
bark() {
return "Woof!";
}
walk() {
this.isTired = true;
}
sleep() {
this.isTired = false;
}
}
var Dog = function(name) {
this.name = name;
this.isTired = false;
};
Dog.prototype.bark = function() {
return "Woof!";
};
Dog.prototype.walk = function() {
this.isTired = true;
};
Dog.prototype.sleep = function() {
this.isTired = false;
};