📘

Ruby Gold 練習問題3回目の振り返り

2022/02/20に公開

こんにちは。WEBエンジニアのホリさんです。
今回が第7回目の記事です。

概要

Ruby Goldの問題3回目を解いて、初めて知ったことについて共有させていただきます。

Module#refine

ブロック内のselfは無名モジュールになります。
以下のようにusing Rを定義すると、refine内のself.testが呼び出されると思いますが、selfは無名モジュールになるため、classのCのhelloが表示されます。
※usingはselfメソッド内では使えないです。

class C
  def self.test
    "hello"
  end
end

module R
  refine C do
    def self.test
      "hello mike"
    end
  end
end

using R

puts C.m1

=> "hello"

inspect

オブジェクトを人間が読める形式に変換した文字列。
以下のようにBar.new.inspectで、オブジェクト情報と同様の結果は
Bar.newでも返すことが可能です。

class Bar
  def initialize
    @bar = 1
  end
end
Bar.new.inspect 

=> "#<Bar:0x0300c868 @bar=1>"

Object.singleton_class

特異クラスを取得することができる。
特異クラスでselfを参照するとレシーバのオブジェクトが取得できます。

class C
  def self._singleton
    class << C
      self
    end
  end
end

p C._singleton

=> #<Class:C>

Fiber#resume

実行するとFiber.yieldが最後に実行された行から再開するか、Fiber.newに指定したブロックの最初の評価を行います。

f = Fiber.new do |total|
  Fiber.yield total + 10
end

p f.resume(100) + f.resume(5)

=> 115

yield

メソッド内部でyieldを使いブロックの実行結果を呼び出すことができる

def foo(a)
  a + yield
end

puts foo("Taro") { "1" }
=> Taro1

Proc

Procメソッドはブロックを持ち運びできるようにしたオブジェクトで、callまたは[]で呼び出すことが可能です。

test = Proc.new { |n|
  n * 3
}

puts test[2] * 2

=> 12

破壊的メソッドの場合は以下の通りエラーになる

a2 = "foo".freeze
a2.replace("bar") # can't modify frozen String (FrozenError)

Singleton

Singletonモジュールをインクルードすると、クラスメソッドinstanceを定義します。
オブジェクトIDがすべて同じ値を返していることから1つのインスタンスしか返せないことが分かります。

require 'singleton'

class Test
  include Singleton

  def foo
    'test'
  end
end

p Test.instance.foo
p Test.instance.__id__ # 700333300
p Test.instance.__id__ # 700333300

=>
"Hi, good morning!"

method_missing

method_missingは、継承先でもメソッドが見つからなかった場合に、呼び出されます。
モージュルにもmethod_missingがある場合でも、呼び出し元の今回だとBインスタンスのmethod_missingが優先的に呼ばれます。

module M
  def method_missing(id, *args)
    puts "C#method_missing"
  end
end
class A
  include M
  def method_missing(id, *args)
    puts "A#method_missing"
  end
end
class B < A
  def method_missing(id, *args)
    puts "B#method_missing"
  end
end

obj = B.new
obj.test_method

=> "B#method_missing"

Module.nesting

ネストの状態を表示します。
ネスト状態はすべて表示されますがネストが内側から順に表示されます。

module Test1
  module Test2
    p Module.nesting
  end
end

=> [Test1::Test2, Test1]

selfのスーパークラス

selfはnewされたクラスのオブジェクトを指します。
スーパークラスでselfを参照したとしても、呼び出ししたクラスのnewのオブジェクトになります。

class Test1
  def initialize
    p self.class
  end
end

class Test2 < Test1
end

Test2.new

=> Test2

beginのRuntimeError

RuntimeErrorはraiseの引数がない場合に発生する

begin
  raise
rescue => e
  puts e.class
end

superの引数

superを定義すると現在のメソッドと同じ引数が引き継がれます。
引数を渡さずにオーバーライドしたメソッドを呼び出す際はsuper()と指定する必要があります。

class Test1
  def initialize
    puts "Test1"
  end
end

class Test2 < Test1
  def initialize(*args)
    super()
    puts "Test2"
  end
end

Test2.new(1,2,3,4,5)

参考URL

https://qiita.com/k-penguin-sato/items/7f98335ef631ea5ce7ad

Discussion