Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes,...
Transcript of Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes,...
![Page 1: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/1.jpg)
Classboxes, nested methods, and real private methods
Shugo Maeda2010-11-12
![Page 2: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/2.jpg)
Self introduction
Shugo Maeda
A Ruby committer
A director of Network Applied Communication Laboratory Ltd. (NaCl)
The co-chairperson of the Ruby Association
01 77
![Page 3: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/3.jpg)
Where am I from?
Matsue, Shimane, Japan
A sister city of New Orleans
02 77
![Page 4: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/4.jpg)
We are different
03 77
![Page 5: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/5.jpg)
Please accept us
04 77
![Page 6: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/6.jpg)
Topics
were supposed to be:
classboxes,
nested methods,
and real private methods
But...
05 77
![Page 7: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/7.jpg)
Topic
A new feature "Refinements"
06 77
![Page 8: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/8.jpg)
What are Classboxes?
A way to extend classes
07 77
![Page 9: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/9.jpg)
How to extend classes in Ruby?
Subclassing
Mix-in
Singleton methods
Open classes
08 77
![Page 10: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/10.jpg)
Subclassing
class Person attr_accessor :nameend
class Employee < Person attr_accessor :monthly_salaryend
09 77
![Page 11: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/11.jpg)
Aspects of subclassing
Normal single inheritance
Subclassing affects only instances of the subclasses
Implementation-only inheritance
Violations of LSP
10 77
![Page 12: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/12.jpg)
LSP
Liskov Substitution Principle
An instance of a subtype must behave like an instance of the supertype of the subtype
An instance of the supertype can be substituted with an instance of the subtype
11 77
![Page 13: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/13.jpg)
An example of LSP
def print_name(person) puts person.nameend
shugo = Person.newshugo.name = "Shugo Maeda"print_name(shugo) #=> Shugo Maedamatz = Employee.newmatz.name = "Yukihiro Matsumoto"print_name(matz) #=> Yukihiro Matsumoto
12 77
![Page 14: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/14.jpg)
A typical LSP violation
class Rectangle attr_accessor :width, :heightend
class Square < Rectangle def set_size(x) @height = @width = x end alias width= set_size alias height= set_sizeend
def set_size(rect) rect.width = 80; rect.height = 60endsquare = Square.newset_size(square)p square.width #=> not 80, but 60!
13 77
![Page 15: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/15.jpg)
A Ruby-specific LSP violation
class Employee < Person undef nameend
def print_name(person) puts person.nameend
matz = Employee.newmatz.name = "Yukihiro Matsumoto"print_name(matz) #=> undefined method `name'...
14 77
![Page 16: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/16.jpg)
Subclassing != Subtyping
Implementation-only inheritance
Duck typing
15 77
![Page 17: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/17.jpg)
Mix-in
class; Stream; ... endmodule Readable; ... endmodule Writable; ... end
class ReadStream < Stream include Readableendclass WriteStream < Stream include Writableendclass ReadWriteStream include Writable, Readableend
16 77
![Page 18: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/18.jpg)
Aspects of mix-in
Limited multiple inheritance
Only modules can be multiply inherited
A module has no instances
Modules are also used as namespaces for constants
17 77
![Page 19: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/19.jpg)
Singleton methods
matz = Person.newdef matz.design_ruby ...endmatz.design_rubyshugo = Person.newshugo.design_ruby #=> NoMethodError
18 77
![Page 20: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/20.jpg)
Aspects of singleton methods
Clients of a class can extend the behavior of an instance of the class
A singleton method defines the behavior of only one particular instance
Some objects cannot have singleton methods
e.g., instances of Integer
19 77
![Page 21: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/21.jpg)
Open classes
# reopen Person, and add codeclass Person attr_accessor :ageendshugo = Person.newshugo.name = "Shugo Maeda"shugo.age = 34
20 77
![Page 22: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/22.jpg)
Aspects of open classes
Clients of a class can extend the behavior of instances of the class
Classes are extended globally
21 77
![Page 23: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/23.jpg)
Applications of open classes
Ruby on Rails
jcode / mathn
22 77
![Page 24: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/24.jpg)
Ruby on Rails
A good example of monky patching
23 77
![Page 25: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/25.jpg)
Jealous of DHH not for...
24 77
![Page 26: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/26.jpg)
But for ActiveSupport
DHH can extend Ruby without permissions from Matz
# This doesn't work on plain Ruby!puts 3.days.ago
25 77
![Page 27: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/27.jpg)
Rails Plugins
Plugins extend framework classes by monky patching
Using alias to call original methods
alias_method_chain
26 77
![Page 28: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/28.jpg)
jcode / mathn
jcode
Adds and refines methods of String for Japanese character handling
mathn
Provides mathematically natural operations on numbers
Bad examples of monkey patching
27 77
![Page 29: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/29.jpg)
LSP and open classes
s/subtype/class after reopen/g
s/supertype/class before reopen/g
Instances of a class after a reopen must behave like instances of the class before the reopen
28 77
![Page 30: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/30.jpg)
an LSP violation
p 1 / 2 #=> 0require "mathn"p 1 / 2 #=> (1/2)
29 77
![Page 31: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/31.jpg)
Summary
Subclassing not by clients
Mix-in not by clients
Singleton methods per object
Open classes global
30 77
![Page 32: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/32.jpg)
Extensibility and Modularity
Subclassing, mix-in, and singleton methods are less extensible
Open classes are less modular
31 77
![Page 33: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/33.jpg)
What we need
Class extensions
by clients
per class
local
32 77
![Page 34: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/34.jpg)
Possible solutions
selector namespace
Classboxes
33 77
![Page 35: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/35.jpg)
selector namespace
Implemented in SmallScript and ECMAScript 4
A namespace of method names (selectors)
A namespace can be imported into other namespaces
Lexically scoped
34 77
![Page 36: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/36.jpg)
Classboxes
Implemented in Squeak and Java
A classbox is a module where classes are defined and/or extended
A classbox can be imported into other classboxes
Dynamically scoped
called local rebinding
35 77
![Page 37: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/37.jpg)
An example of Classbox/J
package Foo;public class Foo { ... }
package Bar;import Foo;refine Foo { public void bar() { ... } }
package Baz;import Bar;public class Baz { public static void main(String[] args) { new Foo().bar(); }}
36 77
![Page 38: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/38.jpg)
An example of local rebinding
package Foo;public class Foo { public void bar() { System.out.println("original"); } public void call_bar() { bar(); }}
package Bar;import Foo;refine Foo { public void bar() { System.out.println("refined"); } }
package Baz;import Bar;public class Baz { public static void main(String[] args) { new Foo().call_bar(); }}
37 77
![Page 39: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/39.jpg)
Is local rebinding needed?
Local rebinding is less modular
Callees might expect the original behavior
Learn from the history of local variable scoping
Singleton methods and open classes can be alternatives
However, effective scopes are different
38 77
![Page 40: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/40.jpg)
Refinements
A newly implemented feature of Ruby
Not merged into the official Ruby repository
Refinements of classes are defined per module
Effective scopes are explicitly specified
no local rebinding
Classbox/J like syntax
39 77
![Page 41: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/41.jpg)
An example of Refinements
module MathN refine Fixnum do def /(other) quo(other) end endend
class Foo using MathN
def bar p 1 / 2 #=> (1/2) endendp 1 / 2 #=> 0
40 77
![Page 42: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/42.jpg)
Demo
41 77
![Page 43: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/43.jpg)
Module#refine
refine(klass, &block)
Additional or overriding methods of klass are defined in block
a set of such methods is called a refinement
Activated only in the receiver module, and scopes where the module is imported by using
refine can also be invoked on classes
42 77
![Page 44: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/44.jpg)
Class local refinements
class Foo refine Fixnum do def /(other) quo(other) end end
def bar p 1 / 2 #=> (1/2) endendp 1 / 2 #=> 0
43 77
![Page 45: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/45.jpg)
Kernel#using
using(mod)
using imports refinements defined in mod
Refinements are activated only in a file, module, class, or method where using is invoked
lexically scoped
44 77
![Page 46: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/46.jpg)
An example of using
using A # A is activated in this file
module Foo using B # B is activated in Foo (including Foo::Bar)
class Bar using C # C is activated in Foo::Bar
def baz using D # D is activated in this method end endend
45 77
![Page 47: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/47.jpg)
Module#using
using(mod)
Module#using overrides Kernel#using
The basic behavior is the same as Kernel#using
Besides, Module#using supports reopen and inheritance
46 77
![Page 48: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/48.jpg)
An example of Module#using
module A; refine(X) { ... } endmodule B; refine(X) { ... } endclass Foo; using A endclass Foo # A is activated in a reopened definition of Fooendmodule Bar using B class Baz < Foo # A is activated in a subclass Baz of Foo # A has higher precedence than B endend
47 77
![Page 49: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/49.jpg)
using and include
module A; refine(X) { ... } endmodule Foo; using A endclass Bar include Foo # include does not activate Aend
48 77
![Page 50: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/50.jpg)
Precedence of refinements
Refinements imported in subclasses have higher precedence
Later imported refinements have higher precedence
Refinements imported in the current class or its superclasses have higher precedence than refinements imported in outer scopes
If a refined class has a subclass, methods in the subclass have higher precedence than those in the refinement
49 77
![Page 51: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/51.jpg)
An example of precedence
class Foo; endmodule Bar; refine Foo do end endmodule Baz; refine Foo do end endclass Quux < Foo; endclass Quuux using Barendmodule Quuuux using Baz class Quuuuux < Quuux def foo # Quux -> Bar -> Baz -> Foo Quux.new.do_something end endend
50 77
![Page 52: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/52.jpg)
Using original features
super in a refined method invokes the original method, if any
If there is a method with the same name in a previously imported refinements, super invokes the method
In a refined method, constants and class variables in the original class is also accessible
51 77
![Page 53: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/53.jpg)
An example of super
module FloorExtension refine Float do def floor(d=nil) if d x = 10 ** d return (self * x).floor.to_f / x else return super() end end endendusing FloorExtensionp 1.234567890.floor #=> 1p 1.234567890.floor(4) #=> 1.2345
52 77
![Page 54: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/54.jpg)
special eval
Refinements are also activated in instance_eval, module_eval, and class_eval
53 77
![Page 55: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/55.jpg)
An example of special eval
class Foo using MathNendFoo.class_eval do p 1 / 2 #=> (1/2)endFoo.new.instance_eval do p 1 / 2 #=> (1/2)end
54 77
![Page 56: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/56.jpg)
Compatibility
No syntax extensions
No new keywords
The behavior of code without refinements never change
However, if existing code has a method named refine or using, it may cause some problems
55 77
![Page 57: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/57.jpg)
Applications of refinements
Refinements of built-in classes
Internal DSLs
Nested methods
56 77
![Page 58: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/58.jpg)
Refinements of built-in classes
Refinements are activated in particular scopes
So you can violate LSP like MathN
Refinement inheritance is useful for frameworks
57 77
![Page 59: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/59.jpg)
Example
class ApplicationController < ActionController::Base using ActiveSupport::All protect_from_forgeryend
class ArticlesController < ApplicationController def index @articles = Article.where("created_at > ?", 3.days.ago) endend
58 77
![Page 60: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/60.jpg)
Internal DSLs
Methods for DSLs need not be available outside DSLs
So these methods can be defined in refinements
instance_eval and module_eval are useful for DSLs
59 77
![Page 61: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/61.jpg)
Example
module Expectations refine Object do def should ... end ... endend
def it(msg, &block) Expectations.module_eval(&block)end
it "returns 0 for all gutter game" do bowling = Bowling.new 20.times { bowling.hit(0) } bowling.score.should == 0end
60 77
![Page 62: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/62.jpg)
Nested methods
def fact(n) # fact_iter is defined in refinements # available only in fact def fact_iter(product, counter, max_count) if counter > max_count product else fact_iter(counter * product, counter + 1, max_count) end end
fact_iter(1, 1, n)end
61 77
![Page 63: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/63.jpg)
Benchmark
make benchmark (5 times)
Environment
CPU: Intel Core 2 Duo U7600 1.2GHz
RAM: 2GB
OS: Linux 2.6.34 (Ubuntu 10.04)
62 77
![Page 64: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/64.jpg)
Additional benchmarks
For refinements
bm_ref_factorial.rb
bm_ref_fib.rb
For nested methods
bm_ref_factorial2.rb
63 77
![Page 65: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/65.jpg)
bm_ref_factorial.rb
if defined?(using) module Fact refine Integer do def fact ... end end end using Factelse class Integer def fact ... end endend
64 77
![Page 66: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/66.jpg)
Benchmark result
Average 2.5% slower than the original Ruby
65 77
![Page 67: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/67.jpg)
Samples
66 77
![Page 68: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/68.jpg)
Considerations
Should include and using be integrated?
Should singleton methods be refinable?
Should modules be refinable?
Implementation improvement
67 77
![Page 69: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/69.jpg)
Should include and using be integrated?
Currently they are independent
module Foo refine Bar { ... } ...end
module Baz # Both include and using are needed # to use mix-in and refinements at the same time include Foo using Fooend
68 77
![Page 70: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/70.jpg)
Workaround
module Foo refine Bar { ... }
def used(klass) klass.send(:include, self) endend
module Baz # using invokes used as a hook using Fooend
69 77
![Page 71: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/71.jpg)
Should singleton methods be refinable?
Currently singleton methods cannot be refined
module Foo # This doesn't work refine Bar do def self.foo end endend
70 77
![Page 72: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/72.jpg)
Workaround
module Foo # This works refine Bar.singleton_class do def foo end endend
71 77
![Page 73: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/73.jpg)
Should modules be refinable?
Currently the argument of refine should be a class
module Fooend
module Bar # This doesn't work refine Foo { ... }end
72 77
![Page 74: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/74.jpg)
Workaround
You can refine a class which includes the module
module Fooend
class Quux include Fooend
module Bar # This works refine Quux { ... }end
73 77
![Page 75: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/75.jpg)
Implementation improvement
It's not my work
ko1 will do it
74 77
![Page 76: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/76.jpg)
Patch
http://shugo.net/tmp/refinement-r29498-20101109.diff
75 77
![Page 77: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/77.jpg)
Conclusion
Refinements achieve a good balance between extensibility and modularity
76 77
![Page 78: Classboxes, nested methods, and real private methodsshugo.net/tmp/rc2010-refinements.pdfClassboxes, nested methods, and real private methods Shugo Maeda 2010-11-12](https://reader034.fdocuments.net/reader034/viewer/2022050206/5f59a222aed6c50c055d8e48/html5/thumbnails/78.jpg)
Thank you
Any questions?
77 77