SlideShare ist ein Scribd-Unternehmen logo
1 von 78
Downloaden Sie, um offline zu lesen
Classboxes, nested methods,
and real private methods
Shugo Maeda
2010-11-12
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
Where am I from?
Matsue, Shimane, Japan
A sister city of New Orleans
02 77
We are different
03 77
Please accept us
04 77
Topics
were supposed to be:
classboxes,
nested methods,
and real private methods
But...
05 77
Topic
A new feature "Refinements"
06 77
What are Classboxes?
A way to extend classes
07 77
How to extend classes in Ruby?
Subclassing
Mix-in
Singleton methods
Open classes
08 77
Subclassing
class Person
attr_accessor :name
end
class Employee < Person
attr_accessor :monthly_salary
end
09 77
Aspects of subclassing
Normal single inheritance
Subclassing affects only instances of the
subclasses
Implementation-only inheritance
Violations of LSP
10 77
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
An example of LSP
def print_name(person)
puts person.name
end
shugo = Person.new
shugo.name = "Shugo Maeda"
print_name(shugo) #=> Shugo Maeda
matz = Employee.new
matz.name = "Yukihiro Matsumoto"
print_name(matz) #=> Yukihiro Matsumoto
12 77
A typical LSP violation
class Rectangle
attr_accessor :width, :height
end
class Square < Rectangle
def set_size(x) @height = @width = x end
alias width= set_size
alias height= set_size
end
def set_size(rect)
rect.width = 80; rect.height = 60
end
square = Square.new
set_size(square)
p square.width #=> not 80, but 60!
13 77
A Ruby-specific LSP violation
class Employee < Person
undef name
end
def print_name(person)
puts person.name
end
matz = Employee.new
matz.name = "Yukihiro Matsumoto"
print_name(matz) #=> undefined method `name'...
14 77
Subclassing != Subtyping
Implementation-only inheritance
Duck typing
15 77
Mix-in
class; Stream; ... end
module Readable; ... end
module Writable; ... end
class ReadStream < Stream
include Readable
end
class WriteStream < Stream
include Writable
end
class ReadWriteStream
include Writable, Readable
end
16 77
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
Singleton methods
matz = Person.new
def matz.design_ruby
...
end
matz.design_ruby
shugo = Person.new
shugo.design_ruby #=> NoMethodError
18 77
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
Open classes
# reopen Person, and add code
class Person
attr_accessor :age
end
shugo = Person.new
shugo.name = "Shugo Maeda"
shugo.age = 34
20 77
Aspects of open classes
Clients of a class can extend the behavior of
instances of the class
Classes are extended globally
21 77
Applications of open classes
Ruby on Rails
jcode / mathn
22 77
Ruby on Rails
A good example of monky patching
23 77
Jealous of DHH not for...
24 77
But for ActiveSupport
DHH can extend Ruby without permissions
from Matz
# This doesn't work on plain Ruby!
puts 3.days.ago
25 77
Rails Plugins
Plugins extend framework classes by monky
patching
Using alias to call original methods
alias_method_chain
26 77
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
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
an LSP violation
p 1 / 2 #=> 0
require "mathn"
p 1 / 2 #=> (1/2)
29 77
Summary
Subclassing not by clients
Mix-in not by clients
Singleton methods per object
Open classes global
30 77
Extensibility and Modularity
Subclassing, mix-in, and singleton methods are
less extensible
Open classes are less modular
31 77
What we need
Class extensions
by clients
per class
local
32 77
Possible solutions
selector namespace
Classboxes
33 77
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
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
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
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
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
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
An example of Refinements
module MathN
refine Fixnum do
def /(other) quo(other) end
end
end
class Foo
using MathN
def bar
p 1 / 2 #=> (1/2)
end
end
p 1 / 2 #=> 0
40 77
Demo
41 77
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
Class local refinements
class Foo
refine Fixnum do
def /(other) quo(other) end
end
def bar
p 1 / 2 #=> (1/2)
end
end
p 1 / 2 #=> 0
43 77
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
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
end
end
45 77
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
An example of Module#using
module A; refine(X) { ... } end
module B; refine(X) { ... } end
class Foo; using A end
class Foo
# A is activated in a reopened definition of Foo
end
module Bar
using B
class Baz < Foo
# A is activated in a subclass Baz of Foo
# A has higher precedence than B
end
end
47 77
using and include
module A; refine(X) { ... } end
module Foo; using A end
class Bar
include Foo
# include does not activate A
end
48 77
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
An example of precedence
class Foo; end
module Bar; refine Foo do end end
module Baz; refine Foo do end end
class Quux < Foo; end
class Quuux
using Bar
end
module Quuuux
using Baz
class Quuuuux < Quuux
def foo
# Quux -> Bar -> Baz -> Foo
Quux.new.do_something
end
end
end
50 77
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
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
end
end
using FloorExtension
p 1.234567890.floor #=> 1
p 1.234567890.floor(4) #=> 1.2345
52 77
special eval
Refinements are also activated in
instance_eval, module_eval, and class_eval
53 77
An example of special eval
class Foo
using MathN
end
Foo.class_eval do
p 1 / 2 #=> (1/2)
end
Foo.new.instance_eval do
p 1 / 2 #=> (1/2)
end
54 77
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
Applications of refinements
Refinements of built-in classes
Internal DSLs
Nested methods
56 77
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
Example
class ApplicationController < ActionController::Base
using ActiveSupport::All
protect_from_forgery
end
class ArticlesController < ApplicationController
def index
@articles = Article.where("created_at > ?", 3.days.ago)
end
end
58 77
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
Example
module Expectations
refine Object do
def should ... end
...
end
end
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 == 0
end
60 77
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
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
Additional benchmarks
For refinements
bm_ref_factorial.rb
bm_ref_fib.rb
For nested methods
bm_ref_factorial2.rb
63 77
bm_ref_factorial.rb
if defined?(using)
module Fact
refine Integer do
def fact ... end
end
end
using Fact
else
class Integer
def fact ... end
end
end
64 77
Benchmark result
Average 2.5% slower than the original Ruby
65 77
Samples
66 77
Considerations
Should include and using be integrated?
Should singleton methods be refinable?
Should modules be refinable?
Implementation improvement
67 77
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 Foo
end
68 77
Workaround
module Foo
refine Bar { ... }
def used(klass)
klass.send(:include, self)
end
end
module Baz
# using invokes used as a hook
using Foo
end
69 77
Should singleton methods be
refinable?
Currently singleton methods cannot be refined
module Foo
# This doesn't work
refine Bar do
def self.foo
end
end
end
70 77
Workaround
module Foo
# This works
refine Bar.singleton_class do
def foo
end
end
end
71 77
Should modules be refinable?
Currently the argument of refine should be a
class
module Foo
end
module Bar
# This doesn't work
refine Foo { ... }
end
72 77
Workaround
You can refine a class which includes the
module
module Foo
end
class Quux
include Foo
end
module Bar
# This works
refine Quux { ... }
end
73 77
Implementation improvement
It's not my work
ko1 will do it
74 77
Patch
http://shugo.net/tmp/refinement-
r29498-20101109.diff
75 77
Conclusion
Refinements achieve a good balance between
extensibility and modularity
76 77
Thank you
Any questions?
77 77

Weitere ähnliche Inhalte

Was ist angesagt?

java-06inheritance
java-06inheritancejava-06inheritance
java-06inheritanceArjun Shanka
 
+2 CS class and objects
+2 CS class and objects+2 CS class and objects
+2 CS class and objectskhaliledapal
 
Interfaces in JAVA !! why??
Interfaces in JAVA !!  why??Interfaces in JAVA !!  why??
Interfaces in JAVA !! why??vedprakashrai
 
Method Handles in Java
Method Handles in JavaMethod Handles in Java
Method Handles in Javahendersk
 
Ppl for students unit 4 and 5
Ppl for students unit 4 and 5Ppl for students unit 4 and 5
Ppl for students unit 4 and 5Akshay Nagpurkar
 
What's New In Python 2.5
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5Richard Jones
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat SheetGlowTouch
 
Java session13
Java session13Java session13
Java session13Niit Care
 
Lecture 4_Java Method-constructor_imp_keywords
Lecture   4_Java Method-constructor_imp_keywordsLecture   4_Java Method-constructor_imp_keywords
Lecture 4_Java Method-constructor_imp_keywordsmanish kumar
 
Virtual function
Virtual functionVirtual function
Virtual functionzindadili
 
What's New In Python 2.4
What's New In Python 2.4What's New In Python 2.4
What's New In Python 2.4Richard Jones
 
Detecting Occurrences of Refactoring with Heuristic Search
Detecting Occurrences of Refactoring with Heuristic SearchDetecting Occurrences of Refactoring with Heuristic Search
Detecting Occurrences of Refactoring with Heuristic SearchShinpei Hayashi
 
Z blue interfaces and packages (37129912)
Z blue   interfaces and  packages (37129912)Z blue   interfaces and  packages (37129912)
Z blue interfaces and packages (37129912)Narayana Swamy
 
Oop04 6
Oop04 6Oop04 6
Oop04 6schwaa
 
Implementation of interface9 cm604.30
Implementation of interface9 cm604.30Implementation of interface9 cm604.30
Implementation of interface9 cm604.30myrajendra
 
Lecture - 3 Variables-data type_operators_oops concept
Lecture - 3 Variables-data type_operators_oops conceptLecture - 3 Variables-data type_operators_oops concept
Lecture - 3 Variables-data type_operators_oops conceptmanish kumar
 

Was ist angesagt? (20)

java-06inheritance
java-06inheritancejava-06inheritance
java-06inheritance
 
Cheat Sheet java
Cheat Sheet javaCheat Sheet java
Cheat Sheet java
 
+2 CS class and objects
+2 CS class and objects+2 CS class and objects
+2 CS class and objects
 
Interfaces in JAVA !! why??
Interfaces in JAVA !!  why??Interfaces in JAVA !!  why??
Interfaces in JAVA !! why??
 
Method Handles in Java
Method Handles in JavaMethod Handles in Java
Method Handles in Java
 
Ppl for students unit 4 and 5
Ppl for students unit 4 and 5Ppl for students unit 4 and 5
Ppl for students unit 4 and 5
 
What's New In Python 2.5
What's New In Python 2.5What's New In Python 2.5
What's New In Python 2.5
 
Java Cheat Sheet
Java Cheat SheetJava Cheat Sheet
Java Cheat Sheet
 
Core java
Core javaCore java
Core java
 
Java session13
Java session13Java session13
Java session13
 
Lecture 4_Java Method-constructor_imp_keywords
Lecture   4_Java Method-constructor_imp_keywordsLecture   4_Java Method-constructor_imp_keywords
Lecture 4_Java Method-constructor_imp_keywords
 
Virtual function
Virtual functionVirtual function
Virtual function
 
What's New In Python 2.4
What's New In Python 2.4What's New In Python 2.4
What's New In Python 2.4
 
Detecting Occurrences of Refactoring with Heuristic Search
Detecting Occurrences of Refactoring with Heuristic SearchDetecting Occurrences of Refactoring with Heuristic Search
Detecting Occurrences of Refactoring with Heuristic Search
 
Java interface
Java interfaceJava interface
Java interface
 
Z blue interfaces and packages (37129912)
Z blue   interfaces and  packages (37129912)Z blue   interfaces and  packages (37129912)
Z blue interfaces and packages (37129912)
 
Interface
InterfaceInterface
Interface
 
Oop04 6
Oop04 6Oop04 6
Oop04 6
 
Implementation of interface9 cm604.30
Implementation of interface9 cm604.30Implementation of interface9 cm604.30
Implementation of interface9 cm604.30
 
Lecture - 3 Variables-data type_operators_oops concept
Lecture - 3 Variables-data type_operators_oops conceptLecture - 3 Variables-data type_operators_oops concept
Lecture - 3 Variables-data type_operators_oops concept
 

Andere mochten auch

Rubyによるデータ解析
Rubyによるデータ解析Rubyによるデータ解析
Rubyによるデータ解析Shugo Maeda
 
人狼知能プログラミング演習資料2015
人狼知能プログラミング演習資料2015人狼知能プログラミング演習資料2015
人狼知能プログラミング演習資料2015Kosuke Shinoda
 
8つの魔法の習得 -RとRubyによるデータ解析入門より-
8つの魔法の習得 -RとRubyによるデータ解析入門より-8つの魔法の習得 -RとRubyによるデータ解析入門より-
8つの魔法の習得 -RとRubyによるデータ解析入門より-Yuki Shimizu
 
Rubyと機械学習の現状
Rubyと機械学習の現状Rubyと機械学習の現状
Rubyと機械学習の現状Aki Ariga
 
スタートアップにjoinして安心して眠るためにやった5つのこと
スタートアップにjoinして安心して眠るためにやった5つのことスタートアップにjoinして安心して眠るためにやった5つのこと
スタートアップにjoinして安心して眠るためにやった5つのことMasashi Ogawa
 
Awsとrubyで作るビッグデータ解析の裏側
Awsとrubyで作るビッグデータ解析の裏側Awsとrubyで作るビッグデータ解析の裏側
Awsとrubyで作るビッグデータ解析の裏側Shohei Kobayashi
 
Ruby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrakeRuby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrakeMasahiro Tanaka
 
HTML5/JavaScript ではじめるIoT
HTML5/JavaScript ではじめるIoTHTML5/JavaScript ではじめるIoT
HTML5/JavaScript ではじめるIoTAtsushi Nakatsugawa
 
RubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみたRubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみたYusuke Kon
 

Andere mochten auch (10)

Rubyによるデータ解析
Rubyによるデータ解析Rubyによるデータ解析
Rubyによるデータ解析
 
人狼知能プログラミング演習資料2015
人狼知能プログラミング演習資料2015人狼知能プログラミング演習資料2015
人狼知能プログラミング演習資料2015
 
8つの魔法の習得 -RとRubyによるデータ解析入門より-
8つの魔法の習得 -RとRubyによるデータ解析入門より-8つの魔法の習得 -RとRubyによるデータ解析入門より-
8つの魔法の習得 -RとRubyによるデータ解析入門より-
 
Pré-Projeto de Pesquisa
Pré-Projeto de PesquisaPré-Projeto de Pesquisa
Pré-Projeto de Pesquisa
 
Rubyと機械学習の現状
Rubyと機械学習の現状Rubyと機械学習の現状
Rubyと機械学習の現状
 
スタートアップにjoinして安心して眠るためにやった5つのこと
スタートアップにjoinして安心して眠るためにやった5つのことスタートアップにjoinして安心して眠るためにやった5つのこと
スタートアップにjoinして安心して眠るためにやった5つのこと
 
Awsとrubyで作るビッグデータ解析の裏側
Awsとrubyで作るビッグデータ解析の裏側Awsとrubyで作るビッグデータ解析の裏側
Awsとrubyで作るビッグデータ解析の裏側
 
Ruby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrakeRuby科学データ処理ツールの開発 NArrayとPwrake
Ruby科学データ処理ツールの開発 NArrayとPwrake
 
HTML5/JavaScript ではじめるIoT
HTML5/JavaScript ではじめるIoTHTML5/JavaScript ではじめるIoT
HTML5/JavaScript ではじめるIoT
 
RubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみたRubyエンジニアがPythonをdisるためにPythonを勉強してみた
RubyエンジニアがPythonをdisるためにPythonを勉強してみた
 

Ähnlich wie Classboxes, nested methods, and real private methods

Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012skinandbones
 
06 InheritanceAndPolymorphism.ppt
06 InheritanceAndPolymorphism.ppt06 InheritanceAndPolymorphism.ppt
06 InheritanceAndPolymorphism.pptParikhitGhosh1
 
UNIT-2.pptx CS3391 Inheritance , types, packages and Interfaces
UNIT-2.pptx CS3391 Inheritance , types, packages and InterfacesUNIT-2.pptx CS3391 Inheritance , types, packages and Interfaces
UNIT-2.pptx CS3391 Inheritance , types, packages and InterfacesSakkaravarthiS1
 
Lightning talk
Lightning talkLightning talk
Lightning talknpalaniuk
 
Metaprogramming Rails
Metaprogramming RailsMetaprogramming Rails
Metaprogramming RailsJustus Eapen
 
Python_Unit_3.pdf
Python_Unit_3.pdfPython_Unit_3.pdf
Python_Unit_3.pdfalaparthi
 
JAVA Notes - All major concepts covered with examples
JAVA Notes - All major concepts covered with examplesJAVA Notes - All major concepts covered with examples
JAVA Notes - All major concepts covered with examplesSunil Kumar Gunasekaran
 
The Ring programming language version 1.7 book - Part 78 of 196
The Ring programming language version 1.7 book - Part 78 of 196The Ring programming language version 1.7 book - Part 78 of 196
The Ring programming language version 1.7 book - Part 78 of 196Mahmoud Samir Fayed
 
Introduction to java
Introduction to javaIntroduction to java
Introduction to javaAjay Sharma
 
L7 inheritance
L7 inheritanceL7 inheritance
L7 inheritanceteach4uin
 

Ähnlich wie Classboxes, nested methods, and real private methods (20)

Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012Reusable Ruby • Rt 9 Ruby Group • Jun 2012
Reusable Ruby • Rt 9 Ruby Group • Jun 2012
 
06 InheritanceAndPolymorphism.ppt
06 InheritanceAndPolymorphism.ppt06 InheritanceAndPolymorphism.ppt
06 InheritanceAndPolymorphism.ppt
 
Only oop
Only oopOnly oop
Only oop
 
UNIT-2.pptx CS3391 Inheritance , types, packages and Interfaces
UNIT-2.pptx CS3391 Inheritance , types, packages and InterfacesUNIT-2.pptx CS3391 Inheritance , types, packages and Interfaces
UNIT-2.pptx CS3391 Inheritance , types, packages and Interfaces
 
Lightning talk
Lightning talkLightning talk
Lightning talk
 
Metaprogramming Rails
Metaprogramming RailsMetaprogramming Rails
Metaprogramming Rails
 
Andy On Closures
Andy On ClosuresAndy On Closures
Andy On Closures
 
Java Inheritance
Java InheritanceJava Inheritance
Java Inheritance
 
Ruby object model
Ruby object modelRuby object model
Ruby object model
 
Java sessionnotes
Java sessionnotesJava sessionnotes
Java sessionnotes
 
Inheritance
InheritanceInheritance
Inheritance
 
13 ruby modules
13 ruby modules13 ruby modules
13 ruby modules
 
Ch5 inheritance
Ch5 inheritanceCh5 inheritance
Ch5 inheritance
 
Lecture 9
Lecture 9Lecture 9
Lecture 9
 
Python_Unit_3.pdf
Python_Unit_3.pdfPython_Unit_3.pdf
Python_Unit_3.pdf
 
JAVA Notes - All major concepts covered with examples
JAVA Notes - All major concepts covered with examplesJAVA Notes - All major concepts covered with examples
JAVA Notes - All major concepts covered with examples
 
The Ring programming language version 1.7 book - Part 78 of 196
The Ring programming language version 1.7 book - Part 78 of 196The Ring programming language version 1.7 book - Part 78 of 196
The Ring programming language version 1.7 book - Part 78 of 196
 
Introduction to java
Introduction to javaIntroduction to java
Introduction to java
 
Sonu wiziq
Sonu wiziqSonu wiziq
Sonu wiziq
 
L7 inheritance
L7 inheritanceL7 inheritance
L7 inheritance
 

Classboxes, nested methods, and real private methods

  • 1. Classboxes, nested methods, and real private methods Shugo Maeda 2010-11-12
  • 2. 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
  • 3. Where am I from? Matsue, Shimane, Japan A sister city of New Orleans 02 77
  • 6. Topics were supposed to be: classboxes, nested methods, and real private methods But... 05 77
  • 7. Topic A new feature "Refinements" 06 77
  • 8. What are Classboxes? A way to extend classes 07 77
  • 9. How to extend classes in Ruby? Subclassing Mix-in Singleton methods Open classes 08 77
  • 10. Subclassing class Person attr_accessor :name end class Employee < Person attr_accessor :monthly_salary end 09 77
  • 11. Aspects of subclassing Normal single inheritance Subclassing affects only instances of the subclasses Implementation-only inheritance Violations of LSP 10 77
  • 12. 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
  • 13. An example of LSP def print_name(person) puts person.name end shugo = Person.new shugo.name = "Shugo Maeda" print_name(shugo) #=> Shugo Maeda matz = Employee.new matz.name = "Yukihiro Matsumoto" print_name(matz) #=> Yukihiro Matsumoto 12 77
  • 14. A typical LSP violation class Rectangle attr_accessor :width, :height end class Square < Rectangle def set_size(x) @height = @width = x end alias width= set_size alias height= set_size end def set_size(rect) rect.width = 80; rect.height = 60 end square = Square.new set_size(square) p square.width #=> not 80, but 60! 13 77
  • 15. A Ruby-specific LSP violation class Employee < Person undef name end def print_name(person) puts person.name end matz = Employee.new matz.name = "Yukihiro Matsumoto" print_name(matz) #=> undefined method `name'... 14 77
  • 16. Subclassing != Subtyping Implementation-only inheritance Duck typing 15 77
  • 17. Mix-in class; Stream; ... end module Readable; ... end module Writable; ... end class ReadStream < Stream include Readable end class WriteStream < Stream include Writable end class ReadWriteStream include Writable, Readable end 16 77
  • 18. 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
  • 19. Singleton methods matz = Person.new def matz.design_ruby ... end matz.design_ruby shugo = Person.new shugo.design_ruby #=> NoMethodError 18 77
  • 20. 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
  • 21. Open classes # reopen Person, and add code class Person attr_accessor :age end shugo = Person.new shugo.name = "Shugo Maeda" shugo.age = 34 20 77
  • 22. Aspects of open classes Clients of a class can extend the behavior of instances of the class Classes are extended globally 21 77
  • 23. Applications of open classes Ruby on Rails jcode / mathn 22 77
  • 24. Ruby on Rails A good example of monky patching 23 77
  • 25. Jealous of DHH not for... 24 77
  • 26. But for ActiveSupport DHH can extend Ruby without permissions from Matz # This doesn't work on plain Ruby! puts 3.days.ago 25 77
  • 27. Rails Plugins Plugins extend framework classes by monky patching Using alias to call original methods alias_method_chain 26 77
  • 28. 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
  • 29. 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
  • 30. an LSP violation p 1 / 2 #=> 0 require "mathn" p 1 / 2 #=> (1/2) 29 77
  • 31. Summary Subclassing not by clients Mix-in not by clients Singleton methods per object Open classes global 30 77
  • 32. Extensibility and Modularity Subclassing, mix-in, and singleton methods are less extensible Open classes are less modular 31 77
  • 33. What we need Class extensions by clients per class local 32 77
  • 35. 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
  • 36. 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
  • 37. 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
  • 38. 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
  • 39. 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
  • 40. 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
  • 41. An example of Refinements module MathN refine Fixnum do def /(other) quo(other) end end end class Foo using MathN def bar p 1 / 2 #=> (1/2) end end p 1 / 2 #=> 0 40 77
  • 43. 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
  • 44. Class local refinements class Foo refine Fixnum do def /(other) quo(other) end end def bar p 1 / 2 #=> (1/2) end end p 1 / 2 #=> 0 43 77
  • 45. 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
  • 46. 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 end end 45 77
  • 47. 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
  • 48. An example of Module#using module A; refine(X) { ... } end module B; refine(X) { ... } end class Foo; using A end class Foo # A is activated in a reopened definition of Foo end module Bar using B class Baz < Foo # A is activated in a subclass Baz of Foo # A has higher precedence than B end end 47 77
  • 49. using and include module A; refine(X) { ... } end module Foo; using A end class Bar include Foo # include does not activate A end 48 77
  • 50. 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
  • 51. An example of precedence class Foo; end module Bar; refine Foo do end end module Baz; refine Foo do end end class Quux < Foo; end class Quuux using Bar end module Quuuux using Baz class Quuuuux < Quuux def foo # Quux -> Bar -> Baz -> Foo Quux.new.do_something end end end 50 77
  • 52. 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
  • 53. 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 end end using FloorExtension p 1.234567890.floor #=> 1 p 1.234567890.floor(4) #=> 1.2345 52 77
  • 54. special eval Refinements are also activated in instance_eval, module_eval, and class_eval 53 77
  • 55. An example of special eval class Foo using MathN end Foo.class_eval do p 1 / 2 #=> (1/2) end Foo.new.instance_eval do p 1 / 2 #=> (1/2) end 54 77
  • 56. 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
  • 57. Applications of refinements Refinements of built-in classes Internal DSLs Nested methods 56 77
  • 58. 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
  • 59. Example class ApplicationController < ActionController::Base using ActiveSupport::All protect_from_forgery end class ArticlesController < ApplicationController def index @articles = Article.where("created_at > ?", 3.days.ago) end end 58 77
  • 60. 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
  • 61. Example module Expectations refine Object do def should ... end ... end end 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 == 0 end 60 77
  • 62. 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
  • 63. 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
  • 65. bm_ref_factorial.rb if defined?(using) module Fact refine Integer do def fact ... end end end using Fact else class Integer def fact ... end end end 64 77
  • 66. Benchmark result Average 2.5% slower than the original Ruby 65 77
  • 68. Considerations Should include and using be integrated? Should singleton methods be refinable? Should modules be refinable? Implementation improvement 67 77
  • 69. 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 Foo end 68 77
  • 70. Workaround module Foo refine Bar { ... } def used(klass) klass.send(:include, self) end end module Baz # using invokes used as a hook using Foo end 69 77
  • 71. Should singleton methods be refinable? Currently singleton methods cannot be refined module Foo # This doesn't work refine Bar do def self.foo end end end 70 77
  • 72. Workaround module Foo # This works refine Bar.singleton_class do def foo end end end 71 77
  • 73. Should modules be refinable? Currently the argument of refine should be a class module Foo end module Bar # This doesn't work refine Foo { ... } end 72 77
  • 74. Workaround You can refine a class which includes the module module Foo end class Quux include Foo end module Bar # This works refine Quux { ... } end 73 77
  • 75. Implementation improvement It's not my work ko1 will do it 74 77
  • 77. Conclusion Refinements achieve a good balance between extensibility and modularity 76 77