Help us understand the problem. What is going on with this article?

メソッド定義と同時に公開レベルを設定するトリビア

More than 1 year has passed since last update.

はじめに

この記事は書籍「プロを目指す人のためのRuby入門」に掲載できなかったトピックを著者自らが紹介するアドベントカレンダーの16日目です。
本文に出てくる章番号や項番号は書籍の中で使われている番号です。

今回はメソッド定義と同時に公開レベルを設定するトリビアをいくつか紹介していきます。

必要な前提知識

「プロを目指す人のためのRuby入門」の第7章まで読み終わっていること。

メソッド定義と同時に公開レベルを設定するトリビア

7.7.2項でも説明したとおり、privateメソッドを定義する場合、Rubyではprivateキーワード(実際はメソッド)の下にメソッドを定義することが多いです。

class User
  # ここから下で定義されたメソッドはprivate
  private

  def hello
    'Hello!'
  end
end

一方、Javaのような他の言語ではメソッド定義ごとにpublicやprivateを指定するものもあります。

public class User {
    // publicメソッド
    public String getHi() {
        return "Hi!";
    }

    // privateメソッド
    private String getHello() {
        return "Hello!";
    }
}

実はRubyでも次のようにしてpublicやprivateをメソッドごとに指定することができます。

class User
  # hiはpublicメソッド
  public def hi
    'Hi!'
  end

  # helloはprivateメソッド
  private def hello
    'Hello!'
  end
end

user = User.new

user.hi
#=> "Hi!"

user.hello
#=> NoMethodError: private method `hello' called for #<User:0x00007fd8f59ca880>

上のようなメソッド定義が可能になる理由

「えー、Rubyにもそんな構文があったの!?」とビックリした人がいるかもしれませんが、これは別にメソッド定義用の特別な構文がRubyに用意されているわけではありません。

上のコードは実際は次のような処理を1つにまとめているだけです。

class User
  # メソッド定義の戻り値を受け取る
  m1 = def hi
    'Hi!'
  end
  # シンボルの:hiが変数に入る
  p m1 #=> :hi
  # publicキーワード(実際はメソッド)にメソッド名を渡す
  public m1

  # メソッド定義の戻り値を受け取る
  m2 = def hello
    'Hello!'
  end
  # シンボルの:helloが変数に入る
  p m2 #=> :hello
  # privateキーワード(実際はメソッド)にメソッド名を渡す
  private m2
end

メソッド定義が戻り値を持つことは「2.12.3 式(Expression)と文(Statement)」を、privateキーワードやpublicキーワードに引数を渡せることは「7.7.6 あとからメソッドの公開レベルを変更する場合」をそれぞれ参照してください。

このように、「メソッド定義が戻り値を持つ」という特徴と、「privateキーワードやpublicキーワードに引数を渡せる」という特徴を組み合わせると、あたかもRubyに専用の構文が用意されているように見せることができます。しかし、実際はこのような書き方をするケースは少ないので、無理に使おうとする必要はありません。

クラスメソッドの場合

クラスメソッドで上のようにメソッド定義と公開レベルの設定を同時に行いたい場合は、class << selfの構文(7.3.4項を参照)でクラスメソッドを定義してください。

class User
  class << self
    # byeはprivateなクラスメソッド
    private def bye
      'Bye!'
    end
  end
end

User.bye
#=> NoMethodError: private method `bye' called for User:Class

次回予告

次回はprivateメソッドをレシーバ付きで呼び出せるケースを説明します。 

jnchito
SIer、社内SEを経て、ソニックガーデンに合流したプログラマ。 「プロを目指す人のためのRuby入門」の著者。 http://gihyo.jp/book/2017/978-4-7741-9397-7 および「Everyday Rails - RSpecによるRailsテスト入門」の翻訳者。 https://leanpub.com/everydayrailsrspec-jp
https://blog.jnito.com/
sonicgarden
「お客様に無駄遣いをさせない受託開発」と「習慣を変えるソフトウェアのサービス」に取り組んでいるソフトウェア企業
http://www.sonicgarden.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした