Ruby – コンソール表示

puts

putsはオブジェクトの内容を表示する。文の実行ごとに改行する。

print

printはオブジェクトの内容を表示する。改行はしない。

p

pはオブジェクトの形式がわかるように表示する。文の実行ごとに改行する。

 

Ruby – クラス

基本形

クラスの基本形は以下の通り。

  • クラス定義はclassで始めてendで終える
  • メソッドはdefで初めてendで終える
  • 初期化メソッド(コンストラクター)は'initialize()'
  • プロパティー(インスタンス変数)は頭に'@'をつけて、initialise()で定義
  • インスタンスの生成は[クラス名].new([引数])

initialize()~コンストラクター

インスタンス生成時の初期化処理をinitialize()に書く(コンストラクター)。インスタンス生成時にinitialize()が内部で実行され、その内容に沿った初期化が行われる(initialize()についてはこちら)。

メソッド

インスタンスメソッドはdef...endで定義する。引数を持たないメソッドの場合、()を省略してメソッド名だけで呼び出せる(これはnewについてもあてはまる)。

インスタンス変数へのアクセス

インスタンス変数はカプセル化(encapsulation、隠蔽)されている。参照したり値をセットしようとするとエラー。

インスタンス変数にアクセスするのにアクセスメソッドによる方法getter/setterを定義する方法がある。

クラス変数・クラスメソッド

クラス変数は、クラスから生成された全インスタンスが共通して利用する変数。

クラスメソッドはクラスレベルで定義されるメソッド。

クラスの継承

継承は'<'を使う。クラスの継承の詳細についてはこちら

 

Ruby – public/protected/private

概要

Rubyにおけるprivateprotectedは、C++やJavaでの振る舞いと一部で異なる。慣れている言語との違いというよりも、Rubyの場合言葉の概念から予想される挙動がシンプルに想起できない。

自クラス内での挙動

以下のコードで自クラス内での挙動を確認する。

直接呼出し

まず次のメソッドに着目する。

これらのメソッドを、インスタンスから直接呼び出した結果。publicメソッドは呼び出せるが、private/protectedメソッドは隠蔽されている。これは想定通り。

関数アクセス

次に、同一クラスの中でこれら3つのメソッドに関数としてアクセスするメソッドの挙動を見てみる。

これらのメソッドをインスタンスから呼び出した結果はすべてエラー無く、同一クラス内からは全て利用可能なことがわかる。

レシーバーアクセス

さらに、関数としてのアクセスではなく、レシーバーのメソッドとしてアクセスするメソッドを試してみる。

同じParentClassの新たなインスタンスを生成し、これを渡してみると、privateメソッドのみエラーとなる。

継承クラスでの挙動

ParentClassの継承クラスChildClassを定義し親クラスのメソッドを呼び出すと、上と同じ結果になり、privateprotectedは隠蔽されている。

関数呼び出しの場合、親クラスのメソッドに全てアクセス可能で、これも自クラス呼び出しと同じ。

別のChildClassのインスタンスを生成し、これをレシーバーとしてメソッドを呼び出すと、privateのみエラーとなる。

なお、関数呼び出し、レシーバー呼び出しの各internalメソッドをChildClass内でオーバーライドしても結果は同じになる。

まとめ

これらをまとめると次のようになる。

public protected private
自クラス
直接コール
× ×
自クラス
関数コール
自クラス
レシーバー
×
継承クラス
直接コール
× ×
継承クラス
関数コール
継承クラス
レシーバー
×

すなわち、public想定通り、関数コールの場合protectedprivateも自クラス・継承クラスに関わらず実行可能。レシーバー呼び出しの場合protectedは実行可能だがprivateは実行不可で、これも自クラス・継承クラスに関わらない。

 

Ruby – クラスメソッド

概要

クラスメソッドは、インスタンスではなくクラスレベルで定義されるメソッド。

定義と利用の方法

インスタンスメソッドは、メソッド名の前に'self.'を付して定義する。

インスタンスメソッドは、[クラス名].[メソッド名]で呼び出す。

インスタンスからは実行不可

インスタンスメソッドから呼び出したり、インスタンスから直接呼び出すことはできない。

 

Ruby – クラス変数

概要

クラス変数はクラスの全員スタンスで共通して参照・定義される変数。各インスタンスが共通の資産を利用するような場合に使われる。

定義方法

クラス変数の定義方法は以下の通り。

  • クラス定義の直下に書く
  • 変数の頭に'@@'をつける
  • メソッド内で使うときも'@@'をつける

このクラス変数に対して、各インスタンスから変更を加えたときの挙動を以下に示す。

なお、クラス変数はカプセル化されており、クラス・インスタンスのどちらからも直接には参照・定義できない。

インスタンス変数と同様にgetter/setterを定義することで参照可能になる。

 

Ruby – クラス – アクセスメソッド

概要

Rubyのインスタンス変数(プロパティー)は、クラス内に隠蔽(encapsulate)されていて、外部からの参照・変更はできないが、アクセスメソッドを使うことで、外部からの参照・変更が可能となる。

attr_reader

attr_readerメソッドを定義すると、そのインスタンス変数を直接参照できるようになる。ただし値のセットはできない。

attr_writer

attr_writerメソッドを定義すると、そのインスタンス変数に直接値をセットできるようになる。ただし参照はできない。

attr_accessor

attr_accessorメソッドを定義すると、そのインスタンス変数の読み書きが直接できるようになる。

無定義での利用

各アクセスメソッドは、initialize()などでインスタンス変数に対してオブジェクトの実態を定義しなくても機能する。ただし無定義のままではnilのままなので、利用時にエラーとなることがある。

initialize()などで明示的に定義するのが望ましい。

複数定義

各アクセスメソッドで','で区切って複数のシンボルを並べることができる。

 

 

Ruby – クラス – getter/setter

概要

Rubyのインスタンス変数(プロパティー)は、Rubyのインスタンス変数(プロパティー)は、クラス内に隠蔽(encapsulate)されていて、外部からの参照・変更はできない。

アクセスメソッドを使うことで参照・変更が可能となるが、それだけだと全くオープンになるだけなので、不適切な値への対処などを体系的に行うことができない。

getter、setterは関数定義にひと手間かかるが、インスタンス変数の参照、代入時の処理が可能となる。以下は、そのコード例。

getter

クラス定義内でgetterを定義する場合、インスタンス変数の名前をそのままメソッド名にして、インスタンス変数の内容を返す。プロパティーを読みだす際に特段の処理が必要な場面はあまり想定されず、アクセスメソッドで公開するのと変わらないと思われる。

setter

関数名を[インスタンス変数名]=([引数])とすることで、セッターを定義できる。セッターの中で、インスタンス変数に値をセットする。

プロパティーへの代入の場合は、その有効性のチェックなどの処理が必要な場合も想定されるので、アクセスメソッドで単に自由に代入を許すよりも、セッターで必要な処理をさせる必要がないか意識すべきと考える。

 

Ruby – クラス~initialize

基本

Rubyのクラスのコンストラクターはinitialize()

initialize()ではなくインスタンスメソッド内でプロパティーを定義することもできる。

ただしこの場合には、プロパティーが定義されるメソッドをプロパティーが参照される前に呼んでおかなければならない(そうしないと演算などで未定義でエラーになる)。

なので、普通はインスタンス生成時に自動的に呼ばれるinitialize()内でプロパティーを定義するのが安全。

オーバーロード不可

異なる引数のコンストラクターを意図してオーバーロードすることはできない。

上記のコードの場合、後の方で定義したコンストラクターは使える。

引数のパターンを変えたいときは、デフォルト引数可変長引数を用いるとよい。

 

Ruby – 関数

関数の定義

関数はdef...endで定義する。その関数が呼び出されるより前に定義されていなければならない。

関数の戻り値

return文で関数の戻り値を指定できる。

再帰呼び出し

再帰呼び出しにも対応。

デフォルト引数

あまりよくない方法

引数のデフォルト値をPythonと同じように指定できる。

実行時に指定した引数は、デフォルト引数があっても引数の順に入れ替えられる。以下の例の8行目で2つの仮引数に対して1つの実引数を与えているが、その値は1つ目の引数に使われている。

以下の6行目で仮引数名yzを指定して実引数を渡しているが、それらの値はxyに与えられてしまう。これは以下の流れによるものと考えられる。

  • 実行時に与えた引数は、デフォルト引数の有無にかかわらず先頭から順番に与えられる
  • 実行時に指定した引数'y=7''z=8'はそれぞれ式として評価され、その値が7、8となる
  • この2つの値が仮引数の先頭から与えられx=7y=8となり、zはデフォルト値の3が使われる

妥当な方法~キーワード引数

仮引数名を指定して実引数を渡す場合は、以下のようにキーワード引数を使うとよい。ただしキーワード引数で仮引数を指定した場合、実行時には指定を省略してデフォルト値を使うか、仮引数を明示して引数を与える必要がある。

デフォルト値を指定しない仮引数と、デフォルト値を指定したキーワード引数は混在して利用可能。

可変長引数

引数の頭に'*'をつけると配列とみなされ、複数の引数を渡せる。

配列の要素を使った処理の例。

通常の引数と可変長の引数が混在する場合、少なくとも通常の引数に対応する引数を渡す必要がある。

可変長引数の内容は空でもよく、まず通常の引数が埋められた後、その数を超える引数が可変長引数となる。

 

Ruby – 条件分岐

if~end節

基本形

一般的なif文の書き方で条件が真のときにthen節が実行される。必ずendで閉じる

else

else節も同じ。

elsif

elseifではなくてelsif

thenの省略

if節やelsif節の後のthenは省略可能。

一行で書く

一行にまとめることは可能。ただしthenがないとエラーになる。

';'で区切ると正常に実行される。

値を返す

if文は条件に対応した節の値を持つ。

後置

実行文の後にif文を置くと、条件が真の場合に文が実行される。

unless文

基本

unlessは条件が真でなければ(偽のときに)then節が実行される。

else

unless文のelse節は条件が真の時(偽でないとき)に実行される。

一行で書く

if文と同じく一行にまとめられる。

後置

実行文の後にunless文を置くと、条件が偽の場合に文が実行される。

case文

基本

case文は複数の条件を順番に確認していく。

thenの省略

thenは省略できる。

値を返す

case文は真となった条件の節の値が戻り値となる。