ログイン
編集不可のページディスカッション情報添付ファイル
"alstamber/2013FreshManRubySeminar4"の差分

MMA
2と11のリビジョン間の差分 (その間の編集: 9回)
2013-04-25 23:31:08時点のリビジョン2
サイズ: 343
編集者: alstamber
コメント:
2013-07-04 23:39:57時点のリビジョン11
サイズ: 9488
編集者: alstamber
コメント:
削除された箇所はこのように表示されます。 追加された箇所はこのように表示されます。
行 1: 行 1:
#acl alstamber:read,write,revert,delete,admin All:read
行 4: 行 2:
 * 2013年度新入生向けRuby講習会の第3回向け資料です。  * 2013年度新入生向けRuby講習会の第4回向け資料です。
行 9: 行 7:
== オブジェクト指向 ==
プログラムをオブジェクトの集合であり、オブジェクト同士が相互に関わりあう事で動作するものと捉え直す考え方。

=== オブジェクトとは ===
プログラムにおけるデータとそれを処理するコードを一かたまりのものとしてみなした概念。

=== プログラムをオブジェクト指向で書く利点 ===
プログラムを複数の固まりに分割することができます。これによって大きなプログラムをより小さな対象に分けて作ることができるようになります。<<BR>>
よって大規模なプログラムを作りやすくなります。

また同じようなことをしているコードを使いまわすことがやりやすくなる。これによって同じようなコードを何度も書かなくて良くなります。
{{{#!highlight ruby
"hoge".reverse #=> "egoh"
}}}
上の例は文字列を逆転させる処理をreverseメソッドにやらせた例です。<<BR>>
文字列を逆転させるような処理をわざわざ書かなくてもすでに作られている文字列を逆転させる処理を使えば良くなるのですごく楽です。
行 10: 行 25:
第2回にてクラスというものについてほんの少し触れました。<<BR>>
クラスにはオブジェクトが持つべきデータや処理の内容が定義されています。<<BR>>
Rubyではオブジェクトの種類をオブジェクトがどのクラスに属しているかをみて判断しています。
行 11: 行 29:
== モジュール == この仕組みのために例えば整数に対してはreverseメソッドは実行できないし、文字列に対してはtimesメソッドを実行することはできません。

=== クラスの定義 ===
クラスには処理(=メソッド)が定義されているという話をしましたが、それはどのように定義されているのでしょうか。

{{{#!highlight ruby
class Hoge
...(中身)...
end
}}}
クラスの定義はclassというキーワードから始まります。<<BR>>
その後ろにクラスの名前を書きます。クラスの名前は必ず大文字から始まらなければいけません。

=== インスタンス ===
たとえば文字列を考えましょう。文字列はStringというクラスに属しているという話をしました。<<BR>>
これは言い換えれば、Stringというクラスに書かれているメソッドなどの定義をもとにして、実際の文字列というオブジェクトが作られているとも言えます。<<BR>>
このように考えた時、クラスに対してクラスを元にして作られた実際のオブジェクトのことを「インスタンス」といいます。<<BR>>
Rubyの文字列はStringクラスのインスタンスです。

=== インスタンスメソッド ===
引き続き文字列について考えましょう。Rubyの文字列に対してはreverseやlengthなどのメソッドを呼び出すことができました。このようなメソッドはインスタンスに対して呼び出されるので、そのことを強調して「インスタンスメソッド」と呼ばれることもあります。

=== インスタンスメソッドの定義 ===
インスタンスメソッドをクラスで定義するにはどうすれば良いのでしょうか。

インスタンスメソッドを定義するには次のように書きます。
{{{#!highlight ruby
class Hoge
    def インスタンスメソッド名
        ...
    end
end
}}}
要はクラスの定義の中にメソッドの定義を普通に書けば良いってことです。

=== クラスの話をすすめるために ===
クラスの話をすすめるために、自分で独自のクラスを作る、という事を考えようと思います。

今回作成するクラスは学生を表すクラスです。名前はStudentにしましょう。

Studentクラスには次のようなデータをおいておけるようにしたいとします。
 * 学籍番号
 * 名前
 * 学科
 * 性別

あとで成績を表すデータも追加しますが、とりあえずはこれだけで。

=== new ===
上のStudentクラスを実際にプログラム中で使うためには、クラスを元にしたインスタンスを作る必要があります。<<BR>>
(Stringクラスがそのままでは使えず、""で囲んだ文字列の形というインスタンスの形にして初めて使えるようになるのと同じです)

Stringクラスの場合、""で文字の並びを囲むことで勝手にStringクラスのインスタンスを作ることができましたが、今作ろうとしているStudentクラスではそういうことはできません。そこでnewという特別なメソッドを使います。

{{{#!highlight ruby
a = Student.new
}}}

上のように書くことで、Studentクラスを元にインスタンスを作って、それをaに代入できます。

それではとりあえず空っぽのStudentクラスを作って、newしてみましょう。
{{{#!highlight ruby
class Student

end

a = Student.new
}}}

==== 問題 ====
上のプログラムを実行すると何か目に見える変化は起きますか?実行せずに予想してみましょう。

=== インスタンス変数 ===
さてStudentクラスからインスタンスを生成したはいいのですが、このインスタンスは意味あるものは何も持っていません。<<BR>>
まずこのインスタンスには学籍番号・名前・学科・性別という情報が一切ありません。<<BR>>
そこでクラスの方にこれらを「インスタンスにはこういうデータを持てるようにしてね」と定義してやる必要があります。<<BR>>

Rubyでデータを保持する方法と言えば変数ですね。つまりいまからインスタンスに変数を持たせるようにプログラムを書きたい、というわけです。<<BR>>
この変数のことを、インスタンスが持っているという点に着目して「インスタンス変数」と呼びます。

=== initializeメソッド ===
initializeメソッドというのは特殊なインスタンスメソッドで、クラスからnewされた時に自動的に実行されることが約束されているメソッドです。

{{{#!highlight ruby
class Student
   def initialize
       (newされたときに実行したいものを書く)
   end
end
}}}

このinitializeメソッドに先ほど説明したインスタンス変数の定義を書いてやれば、newしたときに自動的にインスタンス変数が用意されるんじゃね、という企みなわけです。

インスタンス変数の定義は次のように書きます。
{{{#!highlight ruby
@インスタンス変数名 = 初期値
}}}

いつもの変数定義の前にアットマークを1つつければよいわけですね。

それでは学籍番号・氏名・学科・性別を表すインスタンス変数を作りましょう。
{{{#!highlight ruby
class Student
    def initialize
        @id = 0
        @name = ""
        @dep = ""
        @sex = ""
    end
end
}}}

=== アクセサ ===
さてさてインスタンス変数をせっかく用意したので、インスタンス変数を読んだり、あるいは書き込んだりという事をしたいですね。<<BR>>
インスタンス変数は直接外から見ることはできないので、インスタンス変数を読んだり、書き込んだりするための専用のメソッドを用意する必要があります。具体的には
{{{#!highlight ruby
def get_id
    @id
end

def set_id(new_id)
    @id = new_id
end
}}}
みたいなインスタンスメソッドを定義してやれば
{{{#!highlight ruby
st = Student.new
st.set_id(1011203)
puts st.get_id #1011203と出てくる
}}}

このようにインスタンス変数にアクセスするためのメソッドのことをアクセサ(accessor)と言います。インスタンス変数を読むためのメソッドをゲッター(getter)、書き込むためのメソッドをセッター(setter)といいます。

アクセサをいちいち自分で定義するのは面倒くさいので、アクセサを自動的に作ってくれる方法があります。<<BR>>
クラスの定義の中にattr_accessorメソッドを書いておくと、アクセサを自動的に作ってくれます。<<BR>>
attr_accessorメソッドの引数として、コロンの後ろに変数名を書いたものを渡します。
{{{#!highlight ruby
class Student
    def initialize
       ....
    end

    attr_accessor :id, :name, :dept, :sex
end
}}}

別にゲッターやセッターだけでいいという時もあるでしょう。ゲッターだけ作るときはattr_readerメソッド、セッターだけ作るときはattr_writerメソッドを使います。これらのメソッドを使うとインスタンスメソッド名と同じ名前のアクセサが作られます。

なにこれ

オブジェクト指向

プログラムをオブジェクトの集合であり、オブジェクト同士が相互に関わりあう事で動作するものと捉え直す考え方。

オブジェクトとは

プログラムにおけるデータとそれを処理するコードを一かたまりのものとしてみなした概念。

プログラムをオブジェクト指向で書く利点

プログラムを複数の固まりに分割することができます。これによって大きなプログラムをより小さな対象に分けて作ることができるようになります。
よって大規模なプログラムを作りやすくなります。

また同じようなことをしているコードを使いまわすことがやりやすくなる。これによって同じようなコードを何度も書かなくて良くなります。

   1 "hoge".reverse #=> "egoh"

上の例は文字列を逆転させる処理をreverseメソッドにやらせた例です。
文字列を逆転させるような処理をわざわざ書かなくてもすでに作られている文字列を逆転させる処理を使えば良くなるのですごく楽です。

クラス

第2回にてクラスというものについてほんの少し触れました。
クラスにはオブジェクトが持つべきデータや処理の内容が定義されています。
Rubyではオブジェクトの種類をオブジェクトがどのクラスに属しているかをみて判断しています。

この仕組みのために例えば整数に対してはreverseメソッドは実行できないし、文字列に対してはtimesメソッドを実行することはできません。

クラスの定義

クラスには処理(=メソッド)が定義されているという話をしましたが、それはどのように定義されているのでしょうか。

   1 class Hoge
   2 ...(中身)...
   3 end

クラスの定義はclassというキーワードから始まります。
その後ろにクラスの名前を書きます。クラスの名前は必ず大文字から始まらなければいけません。

インスタンス

たとえば文字列を考えましょう。文字列はStringというクラスに属しているという話をしました。
これは言い換えれば、Stringというクラスに書かれているメソッドなどの定義をもとにして、実際の文字列というオブジェクトが作られているとも言えます。
このように考えた時、クラスに対してクラスを元にして作られた実際のオブジェクトのことを「インスタンス」といいます。
Rubyの文字列はStringクラスのインスタンスです。

インスタンスメソッド

引き続き文字列について考えましょう。Rubyの文字列に対してはreverseやlengthなどのメソッドを呼び出すことができました。このようなメソッドはインスタンスに対して呼び出されるので、そのことを強調して「インスタンスメソッド」と呼ばれることもあります。

インスタンスメソッドの定義

インスタンスメソッドをクラスで定義するにはどうすれば良いのでしょうか。

インスタンスメソッドを定義するには次のように書きます。

   1 class Hoge
   2     def インスタンスメソッド名
   3         ...
   4     end
   5 end

要はクラスの定義の中にメソッドの定義を普通に書けば良いってことです。

クラスの話をすすめるために

クラスの話をすすめるために、自分で独自のクラスを作る、という事を考えようと思います。

今回作成するクラスは学生を表すクラスです。名前はStudentにしましょう。

Studentクラスには次のようなデータをおいておけるようにしたいとします。

  • 学籍番号
  • 名前
  • 学科
  • 性別

あとで成績を表すデータも追加しますが、とりあえずはこれだけで。

new

上のStudentクラスを実際にプログラム中で使うためには、クラスを元にしたインスタンスを作る必要があります。
(Stringクラスがそのままでは使えず、""で囲んだ文字列の形というインスタンスの形にして初めて使えるようになるのと同じです)

Stringクラスの場合、""で文字の並びを囲むことで勝手にStringクラスのインスタンスを作ることができましたが、今作ろうとしているStudentクラスではそういうことはできません。そこでnewという特別なメソッドを使います。

   1 a = Student.new

上のように書くことで、Studentクラスを元にインスタンスを作って、それをaに代入できます。

それではとりあえず空っぽのStudentクラスを作って、newしてみましょう。

   1 class Student
   2 
   3 end
   4 
   5 a = Student.new

問題

上のプログラムを実行すると何か目に見える変化は起きますか?実行せずに予想してみましょう。

インスタンス変数

さてStudentクラスからインスタンスを生成したはいいのですが、このインスタンスは意味あるものは何も持っていません。
まずこのインスタンスには学籍番号・名前・学科・性別という情報が一切ありません。
そこでクラスの方にこれらを「インスタンスにはこういうデータを持てるようにしてね」と定義してやる必要があります。

Rubyでデータを保持する方法と言えば変数ですね。つまりいまからインスタンスに変数を持たせるようにプログラムを書きたい、というわけです。
この変数のことを、インスタンスが持っているという点に着目して「インスタンス変数」と呼びます。

initializeメソッド

initializeメソッドというのは特殊なインスタンスメソッドで、クラスからnewされた時に自動的に実行されることが約束されているメソッドです。

   1 class Student
   2    def initialize
   3        (newされたときに実行したいものを書く)
   4    end
   5 end

このinitializeメソッドに先ほど説明したインスタンス変数の定義を書いてやれば、newしたときに自動的にインスタンス変数が用意されるんじゃね、という企みなわけです。

インスタンス変数の定義は次のように書きます。

   1 @インスタンス変数名 = 初期値

いつもの変数定義の前にアットマークを1つつければよいわけですね。

それでは学籍番号・氏名・学科・性別を表すインスタンス変数を作りましょう。

   1 class Student
   2     def initialize
   3         @id = 0
   4         @name = ""
   5         @dep = ""
   6         @sex = ""
   7     end
   8 end

アクセサ

さてさてインスタンス変数をせっかく用意したので、インスタンス変数を読んだり、あるいは書き込んだりという事をしたいですね。
インスタンス変数は直接外から見ることはできないので、インスタンス変数を読んだり、書き込んだりするための専用のメソッドを用意する必要があります。具体的には

   1 def get_id
   2     @id
   3 end
   4 
   5 def set_id(new_id)
   6     @id = new_id
   7 end

みたいなインスタンスメソッドを定義してやれば

   1 st = Student.new
   2 st.set_id(1011203)
   3 puts st.get_id #1011203と出てくる

このようにインスタンス変数にアクセスするためのメソッドのことをアクセサ(accessor)と言います。インスタンス変数を読むためのメソッドをゲッター(getter)、書き込むためのメソッドをセッター(setter)といいます。

アクセサをいちいち自分で定義するのは面倒くさいので、アクセサを自動的に作ってくれる方法があります。
クラスの定義の中にattr_accessorメソッドを書いておくと、アクセサを自動的に作ってくれます。
attr_accessorメソッドの引数として、コロンの後ろに変数名を書いたものを渡します。

   1 class Student
   2     def initialize
   3        ....
   4     end
   5 
   6     attr_accessor :id, :name, :dept, :sex
   7 end

別にゲッターやセッターだけでいいという時もあるでしょう。ゲッターだけ作るときはattr_readerメソッド、セッターだけ作るときはattr_writerメソッドを使います。これらのメソッドを使うとインスタンスメソッド名と同じ名前のアクセサが作られます。

alstamber/2013FreshManRubySeminar4 (最終更新日時 2013-07-04 23:39:57 更新者 alstamber)