0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Rubyの特異メソッドについて

Posted at

環境

Ubuntu 20.4
Ruby 2.6

はじめに

Rubyには特異メソッドといったものがあります。特異メソッドとは、クラスの内部ではない場所に独立したメソッドを書き、あたかも、そのクラスの内部に実在しているかのように扱うメソッドのことです。また、拡張的な使い方として、superメソッドを使うことで、クラスの内部に実在するメソッドに対し、機能を追加することもできます。

自身の経験上、特異メソッドを使わざるを得ない状況に陥ったことは、一度もありません。殆ど、個人でしか開発を行った経験がないため、自分で作ったクラスにメソッドを追加したい場合は、実際に、クラスに追加すれば済むためだけの話だからです。

勉強のためだけの目的でむりやり特異メソッドを使って、メソッドを追加してもいいのだが、後々の可読性、メンテナンス性のことを考えると、あまりしたくはありません。他人が見たとき、「ん?、この人は、何がやりたいのだろう?」となってしまう可能性が非常に高いです。

恐らくではあるが、特異メソッドを使うケースとして、他人が作成したクラスに対し、「このクラスにメソッドを追加したい!」といった衝動に駆られるが、安易にカスタマイズができない事情がある場合は、特異メソッドを使って追加することになるかと思います。

そもそもメソッドは、クラスを作った人のルールに従って、ルール通りの使い方をするのではなく、自由に使っていいんだよというメッセージが、特異メソッドにはあるのかも知れません。自由である反面、やたら多用すると、それはそれで辟易しそうな気がするので、他人には使って欲しくない機能ではあります。あくまでも個人的な感想です。

動作確認

特異メソッドの動きについて動作確認をしてみました。

Testクラスにtest1メソッドがあります。test2メソッドは含まれていません。しかし、Testクラスをインスタンス化して作ったts変数に、test2メソッドを含めることができます。test2メソッドが独立して動いているのはなく、ts変数のメソッドとして動作しているのです。これが特異メソッドです。

test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test2
    puts "OK2"
end

ts.test2

動作結果です。

OK1
OK2

ts.test2の代わりに、 Test.new.test2としてみました。こういう書き方もできるだろうかと思って書いてみたが、この書き方はできません。エラーになります。

test.rb
def Test.new.test2
    puts "OK2"
end

superの使い方

Testクラスの中にあるメソッドと同じ名前のメソッドを、特異メソッドとして記述することもできます。そうすれば、既存のメソッドが上書きされます。

test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test1
    puts "OK2"
end

ts.test1

動作結果です。

OK1
OK2

特異メソッド内にsuperを1行追加すると、superの個所で、Testクラスのtest1メソッドが呼び出されます。

test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test1
    super
    puts "OK2"
end

ts.test1

動作結果です。

OK1
OK1
OK2

superの位置を変えると、Testクラスのtestメソッドが呼び出されるタイミングも変わります。Testクラスのtest1メソッドが実行されて、その後に、特異メソッドであるtest1メソッドが実行されるといった流れとなります。

test.rb
class Test
    def test1
        puts "OK1"
    end
end

ts = Test.new
ts.test1

def ts.test1
    puts "OK2"
    super
end

ts.test1

動作結果です。

OK1
OK2
OK1
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?