Login
Immutable PageDiscussionInfoAttachments
Diff for "alstamber/2013FreshmanRubySeminar5"

MMA
Differences between revisions 6 and 7
Revision 6 as of 2013-06-11 19:36:44
Size: 3184
Editor: alstamber
Comment:
Revision 7 as of 2013-06-11 20:01:44
Size: 7465
Editor: alstamber
Comment:
Deletions are marked like this. Additions are marked like this.
Line 74: Line 74:
クラスAとクラスBがあったとします。この2つに親子関係があるとします。<<BR>>
親子関係があるということは片方が親で、もう片方が子ということになります。ここではクラスAが親で、クラスBが子であるとします。<<BR>>
親の立場にあるクラスをスーパークラスといいます。子の立場にあるクラスをサブクラスといいます。

クラスが親子関係にあると、次のようなことがいえるようになります。
{{{
スーパークラスにあるインスタンスメソッドが全てサブクラスでもつかえるようになる
}}}

実際にクラスAとクラスBにメソッドを定義して詳しくみていくことにしましょう。

{{{#!highlight ruby
#このプログラムはこのままではこれから説明するような動きをしない(AとBの間に親子関係があるということを書いていないから)
class A
    def f
        puts "akari"
    end
end

class B
    def g
        puts "kyoko"
    end
end
}}}

この状態で次のプログラムを実行するとどうなるかを考えます。

{{{#!highlight ruby
a = A.new
b = B.new

a.f
a.g
b.f
b.g
}}}

まずa.fについて考えます。クラスAにはメソッドfが定義されているので、それが実行されakariと出力されます。<<BR>>
次にa.gについて考えます。クラスBにはメソッドgは定義されていないので、エラーになります。

さらにb.fについて考えます。クラスBにはメソッドfは定義されていませんが、クラスBのスーパークラスであるクラスAにはメソッドfが定義されています。<<BR>>
なのでそちらが実行されて、akariが出力されます。<<BR>>
最後にb.gについて考えます。クラスBにはメソッドgが定義されているので、kyokoが出力されます。

=== オーバーライド ===
さて次のような疑問が湧いてきた人がいるかもしれません。

{{{
サブクラスとスーパークラスに同じ名前のメソッドがあったらどっちが実行されるの?
}}}

答えは、サブクラスのものが優先される、です。<<BR>>
スーパークラスに既にメソッドが定義されていても、それと同じ名前のメソッドを定義すれば、その内容を上書きできるわけです。<<BR>>
これを上書きという意味の英語を使ってメソッドのオーバーライドといいます。

=== クラスの親子関係の例 ===
クラスの親子関係の例としてみんな大好きなStringクラスを使いましょう。<<BR>>
StringクラスにはスーパークラスとしてComparableクラスというものがあります。<<BR>>
Comparableクラスは比較可能なオブジェクトを表すクラスです。<<BR>>
例えば==という名前のメソッドが定義されています。これは二つのComparableクラスのオブジェクトが等しいかどうかを判定するメソッドです。

StringクラスはComparableクラスのサブクラスなので、この==メソッドを使うことができます。<<BR>>
{{{#!highlight ruby
"hoge" == "fuga"
}}}
のような文字列が等しいかどうかを判定する処理は、内部的にStringクラスの==メソッドを呼びだす処理に書きかえられています。<<BR>>
気持ちとしてはこんな感じ。
{{{#!highlight ruby
"hoge".==("fuga")
}}}
Stringクラスそのものには==メソッドはないですが、StringクラスのスーパークラスになっているComparableクラスには==メソッドが定義されているので、<<BR>>
めでたく比較をすることができる、というわけです。

Comparableクラスは他にも沢山のサブクラスを持っています。小数を表すクラスであるFloatクラスもそのひとつです。<<BR>>
2つのオブジェクトを比較するという処理を一つのクラスにまとめることで、FloatクラスやStringクラスに別々に何度も比較する処理を書かなくてよいので楽ができるというわけですね。
Line 75: Line 152:
親子関係は

クラスもオブジェクト

クラスはオブジェクトを作るための設計図だという話をしました。
ここで驚くべき話があります。実はRubyではクラスもまたオブジェクトなのです!!!!!

RubyではクラスはClassというクラスのインスタンスになっています。

となると当然疑問が湧いてきます。Classというクラスはどのクラスからつくられているの?という疑問です。
答えを正確に説明するのは難しいのですが、ここではClassというクラスのインスタンスは自分自身から作られている、という説明にとどめておきます。

クラスインスタンス変数

クラスもやっぱりオブジェクトなので、今までみてきたオブジェクトと同じように変数を持ったりメソッドを持ったりできます。
最初に、クラス自体のインスタンスが持っている変数についてみていくことにしましょう。

クラス自体のインスタンスが持っている変数をクラスインスタンス変数といいます。そのまんまですね。

クラスインスタンス変数の作りかた

クラスインスタンス変数を作るには次のようにします。

   1 class Hoge
   2     @a = (初期値)
   3 end

ただのインスタンス変数となにが違うのかみてみましょう。

   1 class Hoge
   2     @a = (初期値)
   3 
   4     def f
   5         @b = (初期値)
   6     end
   7 end

インスタンスメソッドの中で定義されるとインスタンス変数になり、外で定義されるとクラスインスタンス変数になります。

クラスメソッド

次はメソッドの話です。クラスも通常のオブジェクトと同じようにメソッドを持つことができます。
このようなメソッドをクラスが持っているメソッドなのでクラスメソッドといいます。

クラスメソッドの定義

クラスメソッドは次のように定義します。

   1 def Hoge
   2     def Hoge.f
   3         (処理)
   4     end
   5 end

メソッド名の頭にクラス名を書けばよいことがわかりますね。

クラスメソッドは次のようにしても定義できます。

   1 def Hoge
   2     class << Hoge
   3         def f
   4             (処理)
   5         end
   6     end
   7 end

この定義の仕方についてより詳しく知りたい人は「特異クラス」でググってください。

クラスには親子関係がある

今までクラスは特にお互い関係なく別個に存在するものとして扱ってきました。しかし現実は違います。
ここではクラス同士がお互いにどのような関係を持っているのかについて見ていきましょう。

実はクラス同士には親子関係といえるような関係が存在します。親子というのはどういうことでしょうか。

クラスAとクラスBがあったとします。この2つに親子関係があるとします。
親子関係があるということは片方が親で、もう片方が子ということになります。ここではクラスAが親で、クラスBが子であるとします。
親の立場にあるクラスをスーパークラスといいます。子の立場にあるクラスをサブクラスといいます。

クラスが親子関係にあると、次のようなことがいえるようになります。

スーパークラスにあるインスタンスメソッドが全てサブクラスでもつかえるようになる

実際にクラスAとクラスBにメソッドを定義して詳しくみていくことにしましょう。

   1 #このプログラムはこのままではこれから説明するような動きをしない(AとBの間に親子関係があるということを書いていないから)
   2 class A
   3     def f
   4         puts "akari"
   5     end
   6 end
   7 
   8 class B
   9     def g
  10         puts "kyoko"
  11     end
  12 end

この状態で次のプログラムを実行するとどうなるかを考えます。

   1 a = A.new
   2 b = B.new
   3 
   4 a.f
   5 a.g
   6 b.f
   7 b.g

まずa.fについて考えます。クラスAにはメソッドfが定義されているので、それが実行されakariと出力されます。
次にa.gについて考えます。クラスBにはメソッドgは定義されていないので、エラーになります。

さらにb.fについて考えます。クラスBにはメソッドfは定義されていませんが、クラスBのスーパークラスであるクラスAにはメソッドfが定義されています。
なのでそちらが実行されて、akariが出力されます。
最後にb.gについて考えます。クラスBにはメソッドgが定義されているので、kyokoが出力されます。

オーバーライド

さて次のような疑問が湧いてきた人がいるかもしれません。

サブクラスとスーパークラスに同じ名前のメソッドがあったらどっちが実行されるの?

答えは、サブクラスのものが優先される、です。
スーパークラスに既にメソッドが定義されていても、それと同じ名前のメソッドを定義すれば、その内容を上書きできるわけです。
これを上書きという意味の英語を使ってメソッドのオーバーライドといいます。

クラスの親子関係の例

クラスの親子関係の例としてみんな大好きなStringクラスを使いましょう。
StringクラスにはスーパークラスとしてComparableクラスというものがあります。
Comparableクラスは比較可能なオブジェクトを表すクラスです。
例えば==という名前のメソッドが定義されています。これは二つのComparableクラスのオブジェクトが等しいかどうかを判定するメソッドです。

StringクラスはComparableクラスのサブクラスなので、この==メソッドを使うことができます。

   1 "hoge" == "fuga"

のような文字列が等しいかどうかを判定する処理は、内部的にStringクラスの==メソッドを呼びだす処理に書きかえられています。
気持ちとしてはこんな感じ。

   1 "hoge".==("fuga")

Stringクラスそのものには==メソッドはないですが、StringクラスのスーパークラスになっているComparableクラスには==メソッドが定義されているので、
めでたく比較をすることができる、というわけです。

Comparableクラスは他にも沢山のサブクラスを持っています。小数を表すクラスであるFloatクラスもそのひとつです。
2つのオブジェクトを比較するという処理を一つのクラスにまとめることで、FloatクラスやStringクラスに別々に何度も比較する処理を書かなくてよいので楽ができるというわけですね。

Objectクラス

親子関係は

alstamber/2013FreshmanRubySeminar5 (last edited 2013-06-12 13:47:38 by alstamber)