HEX
Server: Apache
System: Windows NT MAGNETO-ARM 10.0 build 22000 (Windows 10) AMD64
User: Michel (0)
PHP: 7.4.7
Disabled: NONE
Upload Files
File: C:/Ruby27-x64/share/ri/2.7.0/system/syntax/page-refinements_rdoc.ri
U:RDoc::TopLevel[	iI"syntax/refinements.rdoc:ETcRDoc::Parser::Simpleo:RDoc::Markup::Document:@parts[gS:RDoc::Markup::Heading:
leveli:	textI"Refinements;To:RDoc::Markup::BlankLineo:RDoc::Markup::Paragraph;[	I"RDue to Ruby's open classes you can redefine or add functionality to existing ;TI"Qclasses.  This is called a "monkey patch".  Unfortunately the scope of such ;TI"Lchanges is global.  All users of the monkey-patched class see the same ;TI"Nchanges.  This can cause unintended side-effects or breakage of programs.;T@
o;
;[I"ORefinements are designed to reduce the impact of monkey patching on other ;TI"Ousers of the monkey-patched class.  Refinements provide a way to extend a ;TI"Eclass locally.  Refinements can modify both classes and modules.;T@
o;
;[I" Here is a basic refinement:;T@
o:RDoc::Markup::Verbatim;[I"
class C
;TI"  def foo
;TI"    puts "C#foo"
;TI"  end
;TI"	end
;TI"
;TI"module M
;TI"  refine C do
;TI"    def foo
;TI"      puts "C#foo in M"
;TI"
    end
;TI"  end
;TI"	end
;T:@format0o;
;[I"PFirst, a class +C+ is defined.  Next a refinement for +C+ is created using ;TI"Module#refine.;T@
o;
;[I"LModule#refine creates an anonymous module that contains the changes or ;TI"Srefinements to the class (+C+ in the example).  +self+ in the refine block is ;TI"9this anonymous module similar to Module#module_eval.;T@
o;
;[I")Activate the refinement with #using:;T@
o;;[
I"
using M
;TI"
;TI"c = C.new
;TI"
;TI"!c.foo # prints "C#foo in M"
;T;0S;	;
i;I"
Scope;T@
o;
;[	I"PYou may activate refinements at top-level, and inside classes and modules. ;TI"RYou may not activate refinements in method scope.  Refinements are activated ;TI"Runtil the end of the current class or module definition, or until the end of ;TI"/the current file if used at the top-level.;T@
o;
;[I"QYou may activate refinements in a string passed to Kernel#eval. Refinements ;TI"1are active until the end of the eval string.;T@
o;
;[I"SRefinements are lexical in scope.  Refinements are only active within a scope ;TI"Xafter the call to +using+. Any code before the +using+ statement will not have the ;TI"refinement activated.;T@
o;
;[I"SWhen control is transferred outside the scope, the refinement is deactivated. ;TI"TThis means that if you require or load a file or call a method that is defined ;TI"Boutside the current scope the refinement will be deactivated:;T@
o;;[I"
class C
;TI"	end
;TI"
;TI"module M
;TI"  refine C do
;TI"    def foo
;TI"      puts "C#foo in M"
;TI"
    end
;TI"  end
;TI"	end
;TI"
;TI"def call_foo(x)
;TI"
  x.foo
;TI"	end
;TI"
;TI"
using M
;TI"
;TI"x = C.new
;TI"'x.foo       # prints "C#foo in M"
;TI"*call_foo(x) #=> raises NoMethodError
;T;0o;
;[I"TIf a method is defined in a scope where a refinement is active, the refinement ;TI"Rwill be active when the method is called.  This example spans multiple files:;T@
o;
;[I"
c.rb:;T@
o;;[I"
class C
;TI"	end
;T;0o;
;[I"
m.rb:;T@
o;;[I"require "c"
;TI"
;TI"module M
;TI"  refine C do
;TI"    def foo
;TI"      puts "C#foo in M"
;TI"
    end
;TI"  end
;TI"	end
;T;0o;
;[I"m_user.rb:;T@
o;;[I"require "m"
;TI"
;TI"
using M
;TI"
;TI"class MUser
;TI"  def call_foo(x)
;TI"    x.foo
;TI"  end
;TI"	end
;T;0o;
;[I"
main.rb:;T@
o;;[I"require "m_user"
;TI"
;TI"x = C.new
;TI"m_user = MUser.new
;TI".m_user.call_foo(x) # prints "C#foo in M"
;TI"1x.foo              #=> raises NoMethodError
;T;0o;
;[I"HSince the refinement +M+ is active in <code>m_user.rb</code> where ;TI"C<code>MUser#call_foo</code> is defined it is also active when ;TI"+<code>main.rb</code> calls +call_foo+.;T@
o;
;[I"TSince #using is a method, refinements are only active when it is called.  Here ;TI"Aare examples of where a refinement +M+ is and is not active.;T@
o;
;[I"In a file:;T@
o;;[I"# not activated here
;TI"
using M
;TI"# activated here
;TI"class Foo
;TI"  # activated here
;TI"  def foo
;TI"    # activated here
;TI"  end
;TI"  # activated here
;TI"	end
;TI"# activated here
;T;0o;
;[I"In a class:;T@
o;;[I"# not activated here
;TI"class Foo
;TI"  # not activated here
;TI"  def foo
;TI"    # not activated here
;TI"  end
;TI"  using M
;TI"  # activated here
;TI"  def bar
;TI"    # activated here
;TI"  end
;TI"  # activated here
;TI"	end
;TI"# not activated here
;T;0o;
;[I"UNote that the refinements in +M+ are *not* activated automatically if the class ;TI"+Foo+ is reopened later.;T@
o;
;[I"
In eval:;T@
o;;[I"# not activated here
;TI"eval <<EOF
;TI"  # not activated here
;TI"  using M
;TI"  # activated here
;TI"	EOF
;TI"# not activated here
;T;0o;
;[I"When not evaluated:;T@
o;;[
I"# not activated here
;TI"if false
;TI"  using M
;TI"	end
;TI"# not activated here
;T;0o;
;[I"\When defining multiple refinements in the same module inside multiple +refine+ blocks, ;TI"Kall refinements from the same module are active when a refined method ;TI"E(any of the +to_json+ methods from the example below) is called:;T@
o;;[I"module ToJSON
;TI"  refine Integer do
;TI"    def to_json
;TI"      to_s
;TI"
    end
;TI"  end
;TI"
;TI"  refine Array do
;TI"    def to_json
;TI"7      "[" + map { |i| i.to_json }.join(",") + "]"
;TI"
    end
;TI"  end
;TI"
;TI"  refine Hash do
;TI"    def to_json
;TI"N      "{" + map { |k, v| k.to_s.dump + ":" + v.to_json }.join(",") + "}"
;TI"
    end
;TI"  end
;TI"	end
;TI"
;TI"using ToJSON
;TI"
;TI"Ap [{1=>2}, {3=>4}].to_json # prints "[{\"1\":2},{\"3\":4}]"
;T;0S;	;
i;I"Method Lookup;T@
o;
;[I"GWhen looking up a method for an instance of class +C+ Ruby checks:;T@
o:RDoc::Markup::List:
@type:BULLET:@items[	o:RDoc::Markup::ListItem:@label0;[o;
;[I"QIf refinements are active for +C+, in the reverse order they were activated:;To;;;;[o;;0;[o;
;[I"6The prepended modules from the refinement for +C+;To;;0;[o;
;[I"The refinement for +C+;To;;0;[o;
;[I"5The included modules from the refinement for +C+;To;;0;[o;
;[I"!The prepended modules of +C+;To;;0;[o;
;[I"+C+;To;;0;[o;
;[I" The included modules of +C+;T@
o;
;[I"QIf no method was found at any point this repeats with the superclass of +C+.;T@
o;
;[I"INote that methods in a subclass have priority over refinements in a ;TI"Lsuperclass.  For example, if the method <code>/</code> is defined in a ;TI"Nrefinement for Numeric <code>1 / 2</code> invokes the original Integer#/ ;TI"Ubecause Integer is a subclass of Numeric and is searched before the refinements ;TI"Qfor the superclass Numeric. Since the method <code>/</code> is also present ;TI"Nin child +Integer+, the method lookup does not move up to the superclass.;T@
o;
;[I"ZHowever, if a method +foo+ is defined on Numeric in a refinement, <code>1.foo</code> ;TI"?invokes that method since +foo+ does not exist on Integer.;T@
S;	;
i;I"+super+;T@
o;
;[I"2When +super+ is invoked method lookup checks:;T@
o;;;;[o;;0;[o;
;[I"QThe included modules of the current class.  Note that the current class may ;TI"be a refinement.;To;;0;[o;
;[I"PIf the current class is a refinement, the method lookup proceeds as in the ;TI"!Method Lookup section above.;To;;0;[o;
;[I"QIf the current class has a direct superclass, the method proceeds as in the ;TI"6Method Lookup section above using the superclass.;T@
o;
;[I"MNote that +super+ in a method of a refinement invokes the method in the ;TI"Srefined class even if there is another refinement which has been activated in ;TI"the same context.;T@
S;	;
i;I"Methods Introspection;T@
o;
;[I"jWhen using introspection methods such as Kernel#method or Kernel#methods refinements are not honored.;T@
o;
;[I"0This behavior may be changed in the future.;T@
S;	;
i;I"-Refinement inheritance by Module#include;T@
o;
;[I"PWhen a module X is included into a module Y, Y inherits refinements from X.;T@
o;
;[I"LFor example, C inherits refinements from A and B in the following code:;T@
o;;[I"module A
;TI"  refine X do ... end
;TI"  refine Y do ... end
;TI"	end
;TI"module B
;TI"  refine Z do ... end
;TI"	end
;TI"module C
;TI"  include A
;TI"  include B
;TI"	end
;TI"
;TI"
using C
;TI"2# Refinements in A and B are activated here.
;T;0o;
;[I"ORefinements in descendants have higher precedence than those of ancestors.;T@
S;	;
i;I"Further Reading;T@
o;
;[I"USee https://bugs.ruby-lang.org/projects/ruby-trunk/wiki/RefinementsSpec for the ;TI"Qcurrent specification for implementing refinements.  The specification also ;TI"contains more details.;T:
@file@:0@omit_headings_from_table_of_contents_below0