ようへいの日々精進XP

よかろうもん

俺は Ruby について 1bit も理解していなかったので写経する 〜 オブジェクト指向編 (1) 〜

これは

  • Ruby Gold を受験するにあたって学んでいること等を写経したり, メモったりしています
  • Ruby 技術者認定試験合格教本」を主に参考にしており, 今回は第四章「オブジェクト指向」を写経していきます
  • オブジェクト指向、苦手分野だし, 学ばないといけない事が多いので 2 回くらいに分けて記載予定です

そして, この記事は

既に 2018 年だけど...

qiita.com

初老丸 Advent Calendar 2017 25 日目の記事です.

クラス定義

class 式

Foo クラスの定義.

class Foo
  def initialize(a)
    @a = a
  end
  def method1
    @a
  end
end
foo1 = Foo.new(1)
foo2 = Foo.new(2)
  • クラス名は大文字で始める(クラス名は定数)
  • 小文字で始めると構文エラー

以下のように, Ruby のクラス定義は, 内部がスキップされることなく順に評価される.

$ cat 4-3.rb 
p 1
class Hoge
  p 2
end
p 3
$ ruby 4-3.rb 
1
2
3

インスタンスメソッドと初期化メソッド

インスタンスから生成元のクラスオブジェクトを参照する.

[1] pry(main)> class Foo
[1] pry(main)*   def initialize(a)  
[1] pry(main)*     @a = a    
[1] pry(main)*   end    
[1] pry(main)*   def method1  
[1] pry(main)*     @a    
[1] pry(main)*   end    
[1] pry(main)* end  
=> :method1
[2] pry(main)> foo1 = Foo.new(1)
=> #<Foo:0x00557d56e89e68 @a=1>
[3] pry(main)> foo1.class
=> Foo
[4] pry(main)> foo1.class == Foo
=> true

クラス継承

class FooExt < Foo
  def initialize(a, b)
    @b = b
    super a
  end
  def method2(c)
    @a + @b + c
  end
end

fooExt = FooExt.new(3, 4)
p fooExt.method1
p fooExt.method2(5)

実行例.

[9] pry(main)> class FooExt < Foo
[9] pry(main)*   def initialize(a, b)  
[9] pry(main)*     @b = b    
[9] pry(main)*     super a    
[9] pry(main)*   end    
[9] pry(main)*   def method2(c)  
[9] pry(main)*     @a + @b + c    
[9] pry(main)*   end    
[9] pry(main)* end  
=> :method2
[10] pry(main)> fooExt = FooExt.new(3, 4)
=> #<FooExt:0x00557d5726aed8 @a=3, @b=4>
[11] pry(main)> p fooExt.method1
3
=> 3
[12] pry(main)> p fooExt.method2(5)
12
=> 12

クラスオブジェクトからスーパークラスを取得する.

[13] pry(main)> FooExt.superclass
=> Foo

super

スーパークラスの同名メソッドを呼び出す場合, 以下のように super を用いる.

...
  def initialize(a, b)
    @b = b
    super a
  end
...

super に対して引数を省略すると, メソッドが受け取った引数を「そのまま」スーパークラスの同名メソッドに渡して実行する.

インスタンスメソッド

クラスオブジェクト

継承したクラスオブジェクト

  • foo1 と fooExt は Foo クラスで定義された性質を持つ
  • さらに fooExt は FooExt クラスで性質を持つ

継承関係は横軸で表現される. 右に行くほどより一般的な継承の上位に位置するクラスになる.

メソッドの探索経路

インスタンスメソッドを実行すると...

  • クラスオブジェクトに指定されたメソッドが存在するかどうかを判定する(foo1 の method1 を実行すると, 抽象度を 1 つあげて Foo クラスオブジェクトに method1 が存在するか判定する)
  • 同様に fooExt1 の method2 を実行すると, 1 つ上の FooExt に method2 が存在するかを判定する

メソッドが存在しない場合...

  • そのクラスオブジェクト、次にスーパークラスのクラスオブジェクトを順に辿ってメソッドを探す
  • 最後まで見つからなかった場合には, 例外 NoMethodError が発生する
[14] pry(main)> foo1 = Foo.new(1)
=> #<Foo:0x00557d56f7f930 @a=1>
[15] pry(main)> p foo1.method2
NoMethodError: undefined method `method2' for #<Foo:0x00557d56f7f930 @a=1>
[16] pry(main)> fooExt1 = FooExt.new(3, 4)
=> #<FooExt:0x00557d56ec1250 @a=3, @b=4>
[17] pry(main)> p fooExt1.method1
3
=> 3

継承チェーンと method_missing

継承チェーン

スーパークラスを省略してクラスを定義すると, 自動的に Object クラスを継承する.

[19] pry(main)> Foo.superclass
=> Object

Ruby 1.9 以降では, Object クラスは BasicObject クラスを継承するように変更されている.

[20] pry(main)> Object.superclass
=> BasicObject

クラスの継承チェーンを参照するには Module#ancestors を実行する.

[21] pry(main)> p Foo.ancestors
[Foo, Object, PP::ObjectMixin, Kernel, BasicObject]
=> [Foo, Object, PP::ObjectMixin, Kernel, BasicObject]
[22] pry(main)> p FooExt.ancestors
[FooExt, Foo, Object, PP::ObjectMixin, Kernel, BasicObject]
=> [FooExt, Foo, Object, PP::ObjectMixin, Kernel, BasicObject]

継承チェーンに任意のクラスが含まれているかを判定するには, 比較演算子を用いる.

[24] pry(main)> Foo < Object
=> true
[25] pry(main)> Foo > Object
=> false

オブジェクトが持つインスタンスメソッドを調べるには instance_methods メソッドを用いる. オブジェクトが持つインスタンス変数を調べるには instance_valiables メソッドを用いる.

[29] pry(main)> Foo.instance_methods(false)
=> [:method1]
[30] pry(main)> FooExt.instance_methods(false)
=> [:method2]
[32] pry(main)> foo1.instance_variables
=> [:@a]
[33] pry(main)> fooExt1.instance_variables
=> [:@b, :@a]

尚, instance_methods に false を指定すると, スーパークラスを辿らない.

[46] pry(main)> FooExt.instance_methods.grep(/method\d/)
=> [:method2, :method1]

alias と undef

alias を用いて継承チェーンにあるメソッドに別名を付ける.

alias <新メソッド名> <旧メソッド名>
alias <新グローバル変数名> <旧グローバル変数名>
  • alias 式はメソッドではないので, 間にはカンマを指定しない
  • メソッド名は識別子かシンボルで指定する(文字列では指定出来ない!)

undef を用いて指定されたメソッド定義を取り消す.

undef <メソッド名>
undef <メソッド名>,<メソッド名>
  • alias と同様に識別子かシンボルでメソッドを指定する
  • メソッド名をカンマで区切って複数指定することも可能

以下, 実行例.

[47] pry(main)> class Hoge
[47] pry(main)*   def huga1;end
[47] pry(main)*   def huga2;end  
[47] pry(main)*   alias :huga3 :huga1
[47] pry(main)*   undef :huga2
[47] pry(main)* end  
=> nil
[48] pry(main)> Hoge.instance_methods(false)
=> [:huga1, :huga3]
[50] pry(main)> h = Hoge.new
=> #<Hoge:0x00557d57032378>
[51] pry(main)> h.huga1
=> nil
[52] pry(main)> h.huga2
NoMethodError: undefined method `huga2' for #<Hoge:0x00557d57032378>
[53] pry(main)> h.huga3
=> nil
  • alias メソッドを用いて huga1 メソッドに huga3 という別名を付与している
  • undef メソッドを用いて huga2 メソッドを取り消している
  • huga2 メソッドを実行すると例外が発生する

method_missing

  • メソッドが見つからない場合, NoMethodError が発生する
  • 厳密には Object クラスの method_missing メソッドが呼び出される
  • 第一引数に指定されたメソッド名, 第二引数以降に指定された引数が渡される

以下のように method_missing を上書きすることで, メソッドが見つからない場合の動作をフックすることが出来る.

class Hoge
  def method_missing(m, *args)
    p "called: " + m.to_s
  end
  super # 例外が発生するようにスーパークラスの method_missing を呼び出す
end

以下, 実行例.

[57] pry(main)> class Hoge
[57] pry(main)*   def method_missing(m, *args)
[57] pry(main)*     p "called: " + m.to_s
[57] pry(main)*     super
[57] pry(main)*   end  
[57] pry(main)* end  
=> :method_missing
[58] pry(main)> Hoge.new.no_method
"called: no_method"
NoMethodError: undefined method `no_method' for #<Hoge:0x00557d56f71a10>

オープンクラス

  • class 式はクラスオブジェクトが存在しない場合に生成する
  • 既に暮らすオブジェクトが存在する場合には, そのオブジェクトをもう一度開いて評価する
class Hoge
  def huga1;end
end

class Hoge
  def huga2;end
  alias :huga3 :huga1
  undef :huga2, :method_missing
end

Hoge.instance_methods(false)

以下, 実行例.

[64] pry(main)> class Hoge
[64] pry(main)*   def huga1;end  
[64] pry(main)* end  
=> :huga1
[65] pry(main)> 
[66] pry(main)> class Hoge
[66] pry(main)*   def huga2;end  
[66] pry(main)*   alias :huga3 :huga1  
[66] pry(main)*   undef :huga2, :method_missing  
[66] pry(main)* end  
=> nil
[67] pry(main)> Hoge.instance_methods(false)
=> [:huga1, :huga3]

定義済みのクラスを再定義出来るクラスのことをオープンクラスと呼ぶ. 再オープン出来るのは, 標準提供されている組み込みクラスも再オープン出来る.

class String
  def huga; 1; end
end
p "hoge".huga1

以下, 実行例.

[69] pry(main)> class String
[69] pry(main)*   def huga; 1; end  
[69] pry(main)* end  
=> :huga
[71] pry(main)> p "hoge".huga
1
=> 1

スーパークラスを指定して再オープンする場合, スーパークラスはオープンする前のクラスと同じであること.

class Foo; end
class Bar; end
class Baz < Foo
end

class Baz < Bar
end
class Baz < Foo
end
class Baz
end

以下, 実行例.

[72] pry(main)> class Foo; end
=> nil
[73] pry(main)> class Bar; end
=> nil
[74] pry(main)> class Baz < Foo
[74] pry(main)* end  
=> nil
[75] pry(main)> class Baz < Bar
[75] pry(main)* end  
TypeError: superclass mismatch for class Baz
[76] pry(main)> class Baz < Foo
[76] pry(main)* end  
=> nil
[77] pry(main)> class Baz
[77] pry(main)* end  
=> nil

Mix-in

Mix-in とは

  • 多重継承を実現する機能(※ Ruby の継承は単一検証のみ許可されており, 同時に複数のスーパークラスを持つ多重継承を許していない)

モジュールの定義と include

モジュールとクラスの相違点は以下の通り.

  • モジュールは, 単独ではインスタンス化出来ない(new 出来ない)
  • モジュールは継承出来ない
  • モジュールはクラスや他のモジュールを取り込むことが出来る

以下, モジュール定義例.

module Bar
  def methodA
    @a
  end
end

Module オブジェクトの操作

[1] pry(main)> module Bar
[1] pry(main)*   def methodA  
[1] pry(main)*     @a    
[1] pry(main)*   end    
[1] pry(main)* end  
=> :methodA
[2] pry(main)> Bar.ancestors
=> [Bar]
[4] pry(main)> Bar.instance_methods
=> [:methodA]
[5] pry(main)> Bar.new
NoMethodError: undefined method `new' for Bar:Module

生成した Module オブジェクトは, include メソッドを使用してクラスに取り込むことが出来る.

class FooExt < Foo
  include Bar
end

fooExt1 = FooExt.new(3, 4)
p fooExt1.methodA

以下, 実行例.

[6] pry(main)> class Foo
[6] pry(main)*   def initialize(a)  
[6] pry(main)*     @a = a    
[6] pry(main)*   end    
[6] pry(main)*   def method1  
[6] pry(main)*     @a    
[6] pry(main)*   end    
[6] pry(main)* end  
=> :method1
[7] pry(main)> class FooExt < Foo
[7] pry(main)*   def initialize(a, b)  
[7] pry(main)*     @b = b    
[7] pry(main)*     super a    
[7] pry(main)*   end    
[7] pry(main)*   def method2(c)  
[7] pry(main)*     @a + @b + c    
[7] pry(main)*   end    
[7] pry(main)* end  
=> :method2
[8] pry(main)> class FooExt < Foo
[8] pry(main)*   include Bar
[8] pry(main)* end  
=> FooExt
[9] pry(main)> fooExt1 = FooExt.new(3, 4)
=> #<FooExt:0x00559833bc11c0 @a=3, @b=4>
[10] pry(main)> p fooExt1.methodA
3
=> 3

FooExt インスタンスから Bar モジュールで定義された methodA を実行出来る.

モジュールのメソッド探索

methodA がどのように探索されるのか.

[11] pry(main)> FooExt.ancestors
=> [FooExt, Bar, Foo, Object, PP::ObjectMixin, Kernel, BasicObject]
[12] pry(main)> FooExt.superclass
=> Foo
[13] pry(main)> FooExt.instance_methods(false)
=> [:method2]
  • include が実行されると, インタプリタは指定されたモジュールに対応する無名クラスを作成して, スーパークラスとの間に組み込む
  • 無名クラスは include を実行したクラスのおやすに, 順に挿入される

methodA を持つ 2 つのモジュール Bar と Bar2 を include した場合...

module Bar2
  def methodA
    @a + 1
  end
end

class FooExt < Foo
  include Bar
  include Bar2
end

以下, 実行例.

[14] pry(main)> module Bar2
[14] pry(main)*   def methodA  
[14] pry(main)*     @a + 1    
[14] pry(main)*   end    
[14] pry(main)* end  
=> :methodA
[15] pry(main)> class FooExt < Foo
[15] pry(main)*   include Bar  
[15] pry(main)*   include Bar2  
[15] pry(main)* end  
=> FooExt
[16] pry(main)> fooExt1 = FooExt.new(3, 4)
=> #<FooExt:0x00559832c97b40 @a=3, @b=4>
[17] pry(main)> p fooExt1.methodA
4
=> 4

後者の Bar2 の methodA が最初に見つかって実行される. つまり, 後から include したモジュールのメソッドが優先される.

[18] pry(main)> module M1
[18] pry(main)*   def method1; 1; end
[18] pry(main)* end  
=> :method1
[19] pry(main)> class C1
[19] pry(main)*   def method1; 2; end
[19] pry(main)*   include M1
[19] pry(main)* end  
=> C1
[21] pry(main)> C1.new.method1
=> 2
[22] pry(main)> C1.ancestors
=> [C1, M1, Object, PP::ObjectMixin, Kernel, BasicObject]

上記のようにモジュールと同名のメソッドを include メソッドの実行前に定義した場合, モジュールは継承チェーンに挿入さっるだけなので, 実行順序に関わらず常にそのクラス中のメソッド定義が優先される.

[1] pry(main)> module M1
[1] pry(main)*   def method1; 1; end
[1] pry(main)* end  
=> :method1
[2] pry(main)> class C1
[2] pry(main)*   include M1
[2] pry(main)*   def method1; 2; end
[2] pry(main)* end  
=> :method1
[3] pry(main)> C1.new.method1
=> 2

特異クラス

特異クラスの性質

def <オブジェクト名>.<新たに定義するメソッド名>
...
end

特異メソッドの定義例.

foo1 = Foo.new(1)
def foo1.methodB
  @a + 100
end
p foo1.methodB
foo2 = Foo.new(1)
p foo2.methodB #=> NoMethodError

以下, 実行例.

[2] pry(main)> class Foo
[2] pry(main)*   def initialize(a)
[2] pry(main)*     @a = a
[2] pry(main)*   end  
[2] pry(main)*   def methodA
[2] pry(main)*     @a
[2] pry(main)*   end  
[2] pry(main)* end  
=> :methodA
[3] pry(main)> foo1 = Foo.new(1)
=> #<Foo:0x0055bc095a9748 @a=1>
[4] pry(main)> def foo1.methodB
[4] pry(main)*   @a + 100
[4] pry(main)* end  
=> :methodB
[5] pry(main)> p foo1.methodB
101
=> 101
[6] pry(main)> p foo2.methodB
NameError: undefined local variable or method `foo2' for main:Object

特異メソッドの仕組み

  • 特異クラスと呼ばれるクラスを生成して継承チェーンに組み込む
  • 特異クラスに対応するオブジェクトは, 指定されたインスタンスの生成元をスーパークラスとして指す
  • 特異クラスは無名クラスと同様にインタプリタ内部で使用するクラスで, ユーザーに意識させたくないクラス

特異クラスの参照と再オープン

特異クラスは, 以下のような特殊な構文を使用することで参照することが出来る.

foo1 = Foo.new(1)
singleton_class = class << foo1
  self
end
p singleton_class

特異クラスの再オープン式.

class << 対象オブジェクト
end

以下, 実行例.

[7] pry(main)> singleton_class = class << foo1
[7] pry(main)*   self
[7] pry(main)* end  
=> #<Class:#<Foo:0x0055bc095a9748>>
[8] pry(main)> p singleton_class
#<Class:#<Foo:0x0055bc095a9748>>
=> #<Class:#<Foo:0x0055bc095a9748>>

上記では, 特異クラスを再オープンして self を指定しているが, これは通常のクラス内部の self と同様に, そのクラスを参照する. クラス式では最後に評価された式の結果を返り値として返すので, 返り値は特異クラスのオブジェクトになる.

以下のように特異クラスを再オープンして特異メソッドを定義することも可能.

foo1 = Foo.new(1)
class << foo1
  def methodC; @a + 200; end
end
p foo1.methodC

クラス式の内部で定義しているメソッドは, そのクラスのメソッドになっている. よって, プログラム内の methodC メソッドは << でオープンされた foo オブジェクトの特異クラスのメソッドである.

以下, 実行例.

[11] pry(main)> class << foo1
[11] pry(main)*   def methodC; @a + 200; end  
[11] pry(main)* end  
=> :methodC
[12] pry(main)> p foo1.methodC
201
=> 201

self

  • self は自分自身を示す特別なオブジェクト
  • クラス内部で使う場合はそのクラスを, メソッド内部ではそのメソッドを実行するオブジェクトを保持する
  • メソッドが実行されるオブジェクトのことを, 「メソッドの受け手」という意味でレシーバと呼ぶ
class C1
  p self
  def method1
    self
  end
end
c1 = C1.new
p c1 == c1.method1

以下, 実行例.

[1] pry(main)> class C1
[1] pry(main)*   p self  
[1] pry(main)*   def method1  
[1] pry(main)*     self    
[1] pry(main)*   end    
[1] pry(main)* end  
C1
=> :method1
[2] pry(main)> c1 = C1.new
=> #<C1:0x005621083c1598>
[3] pry(main)> p c1 == c1.method1
true
=> true

メソッドのネスト

  • メソッドは, そのメソッドが定義したクラスに所属する
  • メソッドがネストされた場合, 外側のメソッドが定義されたクラスに定義されるが, 内側のメソッドは外側のメソッドが実行されるまで定義されない
class C2
  def method1
    def method2
    end
  end
end
C2.instance_methods(false)
C2.new.method1
C2.instance_methods(false)

以下, 実行例.

[4] pry(main)> class C2
[4] pry(main)*   def method1  
[4] pry(main)*     def method2    
[4] pry(main)*     end      
[4] pry(main)*   end    
[4] pry(main)* end  
=> :method1
[5] pry(main)> 
[6] pry(main)> C2.instance_methods(false)
=> [:method1]
[7] pry(main)> C2.new
=> #<C2:0x005621085ae090>
[8] pry(main)> C2.instance_methods(false)
=> [:method1]
[10] pry(main)> C2.new.method1
=> :method2
[11] pry(main)> C2.instance_methods(false)
=> [:method1, :method2]

extend メソッド

特異クラスに対して Mix-in を行う場合, 以下のように特異クラスを再オープンして include を実行する.

foo1 = Foo.new(1)
class << foo1
  include Bar
end
p foo1.methodA

以下, 実行例.

[4] pry(main)> class Foo
[4] pry(main)*   def initialize(a)
[4] pry(main)*     @a = a
[4] pry(main)*   end  
[4] pry(main)* end  
=> :initialize
[5] pry(main)> foo1 = Foo.new(1)
=> #<Foo:0x0055bbb54adfa0 @a=1>
[6] pry(main)> class << foo1
[6] pry(main)*   include Bar
[6] pry(main)* end  
=> #<Class:#<Foo:0x0055bbb54adfa0>>
[7] pry(main)> p foo1.methodA
1
=> 1

通常クラスと同じように無名クラスが挿入され, 別のインスタンスである foo2 には影響を与えない.

特異クラスへの Mix-in は良く利用される為, 同じ動作をするメソッドである extend メソッドが用意されている.

foo1 = Foo.new(1)
foo1.extend(Bar)
p foo1.methodA

以下, 実行例.

[8] pry(main)> foo1 = Foo.new(1)
=> #<Foo:0x0055bbb55c0a78 @a=1>
[9] pry(main)> foo1.extend(Bar)
=> #<Foo:0x0055bbb55c0a78 @a=1>
[10] pry(main)> p foo1.methodA
1
=> 1

include を利用するコードと比較して簡潔に書けている.

prepend メソッド

  • include と同様にモジュールのメソッドをクラスに取り込む為のメソッド
  • prepend を呼び出したクラスよりも先にモジュールに対して探索を行う為, 同名メソッドが存在する場合に include と振る舞い異なる
module M1
  def method1; "m1"; end
end

class C1
  prepend M1
  def method1; "c1"; end
end

class C2
  include M1
  def method1; "c2"; end
end

p C1.new.method1
p C2.new.method1

以下, 実行例.

[1] pry(main)> module M1
[1] pry(main)*   def method1; "m1"; end  
[1] pry(main)* end  
=> :method1
[2] pry(main)> 
[3] pry(main)> class C1
[3] pry(main)*   prepend M1  
[3] pry(main)*   def method1; "c1"; end  
[3] pry(main)* end  
=> :method1
[4] pry(main)> 
[5] pry(main)> class C2
[5] pry(main)*   include M1  
[5] pry(main)*   def method1; "c2"; end  
[5] pry(main)* end  
=> :method1
[6] pry(main)> p C1.new.method1
"m1"
=> "m1"
[7] pry(main)> p C2.new.method1
"c2"
=> "c2"
[8] pry(main)> C1.ancestors
=> [M1, C1, Object, PP::ObjectMixin, Kernel, BasicObject]
[9] pry(main)> C2.ancestors
=> [C2, M1, Object, PP::ObjectMixin, Kernel, BasicObject]
  • prepend(先頭に追加する) を使った C1 では, M1 が先にメソッド探索される
  • include を使った C2 では, C2 の方が先にメソッド探索される

prepend メソッド(2)

  • prepend メソッド使うとモジュールがクラスよりも先に呼び出される
  • prepend されたモジュール内で super を呼び出すと, 継承チェーン上のクラスから同名のメソッドを探索し呼び出すことが出来る
  • 継承チェーン上のクラスに存在しなければ NoMethodError となる
module M1
  def method1
    super
    puts "m1"
  end
end

class C1
  prepend M1
  def method1
    puts "c1"
  end
end

C1.new.method1

以下, 実行例.

[14] pry(main)> module M1
[14] pry(main)*   def method1  
[14] pry(main)*     super    
[14] pry(main)*     puts "m1"    
[14] pry(main)*   end    
[14] pry(main)* end  
=> :method1
[15] pry(main)> 
[16] pry(main)> class C1
[16] pry(main)*   prepend M1  
[16] pry(main)*   def method1  
[16] pry(main)*     puts "c1"    
[16] pry(main)*   end    
[16] pry(main)* end  
=> :method1
[17] pry(main)> C1.new.method1
c1
m1
=> nil
[18] pry(main)> C1.ancestors
=> [M1, C1, Object, PP::ObjectMixin, Kernel, BasicObject]

Refinements

  • refine メソッドで変更を加えるクラスを宣言し, using メソッドを呼び出した以降から変更したメソッドの呼び出しが有効になる
  • using が有効になる範囲は, クラス・モジュール定義の外で using を呼び出すとファイルの末尾まで
  • クラス・モジュール定義の中で using を呼び出すとクラス・モジュール定義の末尾まで
class C
  def foo
    puts "C#foo"
  end
  
  def bar
    foo
  end
end

module M
  refine C do
    def foo
      puts "C#foo in M"
    end
  end
end

using M
x = C.new
x.foo
x.bar

以下, 実行例.

$ ruby 4-31.rb 
C#foo in M
C#foo
  • refine 内で定義された変更内容は using メソッドを呼び出した後に有効になる
  • bar メソッドは内部で foo メソッドの呼び出しを行っているが, using が呼び出される前に定義されているので, 書き換え前の foo メソッドを呼び出す

以上

写経でした.

引き続き, 頑張るぞ.