Lisp: Everything is an expression
The followings are expressions:
- Class definition
- Method definition
- if statement
The followings are expressions:
- Class definition
- Method definition
- if statement expression
Valid, but don't do this:
p(if (class C; self; end)
def f a=(def g a; 'g'; end)
g a
end
g f
end) # => 'g'
Smalltalk: Everything is an object
The followings are objects:
- Class
- Method
- TOPLEVEL_BINDING
There's more than one
way to do it (perlish)
Object.instance_method(:p).bind(self).call(self)
# => main
Equivalent to:
p self # => main
Today's Topics:
- Type System
- Static Typing vs Dynamic Typing
- Strong or Weak? Coercion?
- Runtime System (Object Model)
- Object is an Object itself
- Singleton Pattern? Class?
- Muack -- Yet Another Mocking Library
Today's Topics:
- Type System
- Static Typing vs Dynamic Typing
- Strong or Weak? Coercion?
- Runtime System (Object Model)
- Object is an Object itself
- Singleton Pattern? Class?
- Muack -- Yet Another Mocking Library
Static Typing vs
Dynamic Typing
- They are not conflicting
- Think of DT as "unityped" in ST
- Downcasting is dynamic type checking
Extracted from gson
@SuppressWarnings("unchecked")
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
Duck Typing
Duck.new.walk
Could be thought as:
Object duck = new Duck();
if(duck.isRespondingTo("walk"))
duck.dispatch("walk");
else
throw new NoMethodError(duck, "walk");
Today's Topics:
- Type System
- Static Typing vs Dynamic Typing
- Strong or Weak? Coercion?
- Runtime System (Object Model)
- Object is an Object itself
- Singleton Pattern? Class?
- Muack -- Yet Another Mocking Library
Strong or Weak? Coercion?
- Vague terms
- It's not about static typing or dynamic typing
- Sometimes it means implicit type coercion
Perl Type Coercion
'1' + 1 # 2
1 . '1' # '11'
JavaScript Type Nonsense
'1' + 1 // '11'
1 + '1' // '11'
true + true // 2
true + [] // 'true'
More
JavaScript Type Nonsense
ref:
GorillaScript
true + null // 1
true + undefined // NaN
true + {} // 'true[object Object]'
new Date(0) + 0 // 'Thu Jan 01 1970 08:00:00 GMT+0800 (CST)0'
new Date(0) - 0 // 0
Today's Topics:
- Type System
- Static Typing vs Dynamic Typing
- Strong or Weak? Coercion?
- Runtime System (Object Model)
- Object is an Object itself
- Singleton Pattern? Class?
- Muack -- Yet Another Mocking Library
Object is an Object itself?
Ruby:
Object.kind_of?(Object) # true
Java:
Object instanceof Object // ?
If A is a kind of B...
B must either be:
# A's class
B == A.class
# or A's class' superclass
B == A.class.superclass
# or A's class' superclass' superclass
B == A.class.superclass.superclass
# or A's class' superclass' superclass' superclass
B == A.class.superclass.superclass.superclass
# ...
Assume A and B
are both Objects...
# A's class
B == A.class
# or A's class' superclass
B == A.class.superclass
# or A's class' superclass' superclass
B == A.class.superclass.superclass
# or A's class' superclass' superclass' superclass
B == A.class.superclass.superclass.superclass
# ...
Assume A and B
are both Objects...
# => v Class
Object == Object.class
# or A's class' superclass
B == A.class.superclass
# or A's class' superclass' superclass
B == A.class.superclass.superclass
# or A's class' superclass' superclass' superclass
B == A.class.superclass.superclass.superclass
# ...
Assume A and B
are both Objects...
# => v Class
Object == Object.class
# => v Module
Object == Object.class.superclass
# or A's class' superclass' superclass
B == A.class.superclass.superclass
# or A's class' superclass' superclass' superclass
B == A.class.superclass.superclass.superclass
# ...
Assume A and B
are both Objects...
# => v Class
Object == Object.class
# => v Module
Object == Object.class.superclass
# => v Object
Object == Object.class.superclass.superclass
# or A's class' superclass' superclass' superclass
B == A.class.superclass.superclass.superclass
# ...
Assume A and B
are both Objects...
# => v Class
Object == Object.class
# => v Module
Object == Object.class.superclass
# => v Object
Object == Object.class.superclass.superclass
# => v BasicObject
Object == Object.class.superclass.superclass.superclass
# ...
Thus:
Object.new.kind_of?(Object) # true
# because
Object == Object.new.class
Also:
Object .kind_of?(Object) # true
# because
Object == Object .class.superclass.superclass
Smalltalk: Everything is an object
Ruby: Even Object is an Object itself
Cool facts:
Class/Module is also a Class/Module itself
Class.kind_of?(Class ) # => true
# because
Class.class # => Class
# thus
Class == Class.class
Cool facts:
Class/Module is also a Class/Module itself
Module.kind_of?(Module) # => true
# because
Module.class # => Class
# thus
Module == Module.class.superclass
Today's Topics:
- Type System
- Static Typing vs Dynamic Typing
- Strong or Weak? Coercion?
- Runtime System (Object Model)
- Object is an Object itself
- Singleton Pattern? Class?
- Muack -- Yet Another Mocking Library
Singleton Pattern
require 'singleton'
class Mario
include Singleton
def greets
puts "It's me, Mario!"
end
end
Mario.instance.greets
Singleton Pattern Underneath
# (simplified)
class Mario
def self.instance
@instance ||= new
end
def greets
puts "It's me, Mario!"
end
end
Mario.instance.greets
Singleton Pattern *Simplest*
Mario = Object.new
def Mario.greets
puts "It's me, Mario!"
end
Mario.greets
Introducing Singleton Class
Also called
Metaclass (Smalltalk) or
Eigenclass
Mario.singleton_class
# => #<Class:#<Object:0xDEADBEEF>>
Introducing Singleton Class
Also called
Metaclass (Smalltalk) or
Eigenclass
- An instance's method is defined in a class
- In its direct class, or
- In one of its direct class' superclasses, or
- In its singleton_class
An instance's method is defined in its
singleton_class
If and only if
The other instances of the same class do not have the same method
forget about some hacks for now
Mario is an Object
Mario = Object.new
def Mario.greets
puts "It's me, Mario!"
end
Mario.greets
The other Objects do not greet
# ...like a Mario!
# NoMethodError: undefined method `greets'
Object.new.greets
So class methods are
singleton methods!
.
Remember?
An instance's method is defined in its
singleton_class
If and only if
The other instances of the same class do not have the same method
Time is an instance of Class,
But the other Classes
Do not have this method:
Time.at(0)
The other instances of the same class do not have the same method
So class methods are
singleton methods!
Time.class # => Class
Time.at(0) # => 1970-01-01 08:00:00 +0800
Hash.class # => Class
Hash.at(0) # => NoMethodError: undefined method
Time.at is defined in Time's singleton class.
The same as Mario.greet
So class methods are
singleton methods!
def Mario.greet; puts "It's me, Mario!"; end
Mario.singleton_class.module_eval do
def greet; puts "It's me, Mario!"; end
end
Time.at is defined in Time's singleton class.
The same as Mario.greet
Don't get confused.
Ruby's singleton class
Has nothing to do with
Singleton pattern.
...It's eigenclass after all
If
We need to go deeper
For Method Dispatching
Checkout my other slides for:
Rubinius on 2008-12-21
Today's Topics:
- Type System
- Static Typing vs Dynamic Typing
- Strong or Weak? Coercion?
- Runtime System (Object Model)
- Object is an Object itself
- Singleton Pattern? Class?
- Muack -- Yet Another Mocking Library
A taste of Muack
require 'muack'
include Muack::API
Mario = 'Mario'
mock(Mario).greet{ "It's me, #{Mario.reverse}!" }
mock(Mario).reverse.proxy.returns(&:reverse)
puts Mario.greet # "It's me, Mario!"
Muack.verify
- greet and reverse is defined in Mario's singleton class
- Proxy would call super to call the original method
any_instance_of
Luigi = Class.new{
def greet; "It's me, #{self}!" end }
any_instance_of(Luigi) do |luigi|
mock(luigi).to_s.proxy.returns{ |s| s[/\w+/] }
end
puts Luigi.new.greet # It's me, Luigi!
Muack.verify
- greet and to_s is defined in Luigi (not singleton class)
- Proxy would call super to call the original method
Trick in AnyInstanceOf:
Muack::AnyInstanceOf =
Class.new(Struct.new(:singleton_class))
Fake singleton class as class
Muack::AnyInstanceOf.new(Luigi).
singleton_class == Luigi # true
If
We need to go deeper
For Muack
Use the Source, Tux!