Ruby __send__, instance_eval, instance_exec
privateメソッドでも、 sendやinstance_evalならば実行可能
class A private def a @value = "a" puts @value end end obj = A.new obj.__send__(:a) #=> "a" # instance_evalはブロックを実行可能 obj.instance_eval{ puts(@value + "b") }#=> "ab"
instant_execなら引数をとることが可能
class B private def initialize @x = 3 end end B.new.instance_exec(3){|int| (@x ** 2).times{puts "こんにちは"}} #=> こんにちは こんにちは...
Ruby Proc/lambda
Procとlambdaで break時、return、retry時の挙動が異なる。
l1 = lambda {return 10} l2 = lambda {break 20} p l1.call #=> 10 p l2.call #=> 20 p1 = Proc.new {return 10} p2 = Proc.new {break 20} p p1.call #=> unexpected return (LocalJumpError) p p2.call #=> break from proc-closure (LocalJumpError)
Procは、上記の場合、もう作成元、つまりこのばあいmainが終了しているのでエラー
Procは引数の数に違いがあってもnilを付けてブロックを実行
p = Proc.new{|a,b,c| a+b+c} p.call(1,2,3,4) #=> 6 p.call(1,2) #=> TypeError: nil can't be coerced into Fixnum
lambdaは引数エラーが出る
p = lambda{|a,b,c| a+b+c} p.call(1,2,3,4) #=> ArgumentError: wrong number of arguments
Ruby Refinements(2回目)
オープンクラス定義
class String def to_alphanumeric gsub(/[^\w\s]/,'') end end
だが、副作用が発生しやすい
Refinementsは
module StringEnhance refine String do def to_alphanumeric gsub(/[^\w\s]/,'') end end end using StringEnhance p "beautiful, 12, woman @\#\{$%^&}$%^&".to_alphanumeric
Ruby prepend(2度目)
module M1 def hoge "from M1 Module" end end module M2 def hoge "from M2 Module" end end class K prepend M1 include M2 def hoge "from K class" end end p K.new.hoge #=> "from M1 Module"
Ruby 定数
大文字で始まるものは定数
module M MyConstant = "外側" class MyClass MyConstant = "内側" end end p M.constants #=> [:MyConstant, :MyClass]。大文字で始まるものはクラス名であろうがとりあえず全部定数。 p ::M::MyConstant #=> "外側" p ::M::MyClass::MyConstant #=> "内側" Hoge = ::M::MyClass::MyConstant p Hoge #=> "内側"
Module.constantsはトップレベルの定数を全部出力
Module #=> [:Object, :Module, :Class, :BasicObject, :Kernel, :NilClass, :NIL, :Data, :TrueClass, :TRUE, :FalseClass, :FALSE, :Encoding, :Comparable, :Enumerable, :String, :Symbol, :Exception, :SystemExit, :SignalException, :Interrupt, :StandardError, :TypeError, :ArgumentError, :IndexError, :KeyError, :RangeError, :ScriptError, :SyntaxError, :LoadError, :NotImplementedError, :NameError, :NoMethodError, :RuntimeError, :SecurityError, :NoMemoryError, :EncodingError, :SystemCallError, :Errno, :ZeroDivisionError, :FloatDomainError, :Numeric, :Integer, :Fixnum, :Float, :Bignum, :Array, :Hash, :ENV, :Struct, :RegexpError, :Regexp, :MatchData, :Marshal, :Range, :IOError, :EOFError, :IO, :STDIN, :STDOUT, :STDERR, :ARGF, :FileTest, :File, :Dir, :Time, :Random, :Signal, :Process, :Proc, :LocalJumpError, :SystemStackError, :Method, :UnboundMethod, :Binding, :Math, :GC, :ObjectSpace, :Enumerator, :StopIteration, :RubyVM, :Thread, :TOPLEVEL_BINDING, :ThreadGroup, :Mutex, :ThreadError, :Fiber, :FiberError, :Rational, :Complex, :RUBY_VERSION, :RUBY_RELEASE_DATE, :RUBY_PLATFORM, :RUBY_PATCHLEVEL, :RUBY_REVISION, :RUBY_DESCRIPTION, :RUBY_COPYRIGHT, :RUBY_ENGINE, :TracePoint, :ARGV, :Gem, :RbConfig, :Config, :CROSS_COMPILING, :ConditionVariable, :Queue, :SizedQueue, :StringIO, :MonitorMixin, :Monitor, :Exception2MessageMapper, :IRB, :RubyToken, :RubyLex, :Readline, :RUBYGEMS_ACTIVATION_MONITOR]
Ruby クラス作成時のオブジェクト関係
クラスを宣言した時の継承関係
class A; end p A.ancestors #=> [A, Object, Kernel, BasicObject]。先祖 p A.class #=> Class。クラスクラス。 p Class.class #=> Class p Class.superclass #=> Module。モジュールクラスを継承していることに注目 p A.superclass #=> Object p Object.superclass #=> BasicObject p BasicObject.ancestors #=> [BasicObject] p Module.superclass #=> Object p Module.superclass #=> Object
Ruby オープンクラス
\w ....a-zA-Z0-9な文字列、
\s ....空白文字列
これら以外の文字(記号や特殊文字)を消すメソッドを書く
require 'test-unit' class String def changer self.gsub(/[^\w\s]/,"") end end class A < Test::Unit::TestCase def test_changer assert_equal("*()aadaf".changer,"aadaf") end end
既存のクラスは組み込み済みのクラスも含めて 再オープン、再定義可能である