久々の、シリーズ「Ruby1.9、Windowsで」です。
今、クラスの書き方をやっていて、クラスを書いて、属性の変数を書くところまできました。
今日は、継承(Javaのextends)と、横断的関心事が書けるモジュールについてやります。
なお、このシリーズでも、< > ¥は、断りのない限り、本当は半角です。
■継承
継承を使うと、継承元に書いた属性やメソッドを継承先に書かなくて済みます。
・・・ってことなんですけど、そーいう技巧的な話ではなく、ふつう、階層関係があるときに利用します。
クラスにおいて、「動物」、「人間」、「日本人」のように、階層関係があることがあります。
言うまでもなく、例の場合、動物の一種が人間で、人間の一種が日本人なので、
動物-人間-日本人
という階層(親子)関係があります。
このとき、動物全体に共通な話(性別とか)は、動物で定義しましょうと。そーしたら、人間でも、日本人でも、再定義しなくても使えますよと・・
そうすれば、それぞれの種固有の属性(「人間」の「肌の色」とか)のみを子供の(ここでは人間の)クラスで定義すればいいよねと・・
ただし、動物全体で、機能的には同じでも、それぞれの種によって違いがある場合もあるでしょう(走る=動物だと4つ足、人間は、2足歩行)。そこは、それぞれの種(子供のクラス=ここでは人間)で再定義してねと・・
こーいう親子関係を継承といいました。
■継承のあらわしかた
で、Rubyの場合は、< (ほんとうは、半角)で、クラスのところに書いて表現します。
class Ningen < Dobutu
みたいなかんじで、親子をあらわします。
サンプルは、こんなかんじ。
class ZZ attr_accessor :a def putme() puts @a end end class ZZZ < ZZ attr_accessor :aa def putme() puts @aa end def putmea() puts @a end end |
(上記< > ¥は、本当は半角)
上記の場合、ZZが親で、
class ZZZ < ZZ
で継承の宣言をしているため、ZZZでは、
@aaというのが使えるのはもちろん、
ZZで宣言している
@aも使えます。
また、ZZZのputmeは、ZZでもputmeがあるけど、
ZZZで再定義されているので、
ZZZにあるputmeを実行、
つまり@aaが出力されます。
なので、
b=ZZ.new bb=ZZZ.new b.a = 100 bb.a = 200 bb.aa = bb.a + b.a b.putme bb.putme bb.putmea |
(上記< > ¥は、本当は半角)
とやると、
b.putmeでは、b.aの値である100,
bb.putmeでは、bb.aaの値である300
bb.putmeaでは、bb.aの値である200
が表示されます。
■アスペクト指向と横断的関心事
で、オブジェクト指向で、とくにプログラミングファースト開発みたいなかんじで書いた場合、クラスのような、本来の意味的には関係ないんだけど、共通の機能というのが出てきます。
とくに、デバッグ・テストに関するものや、チェックに関する機能など・・・
数字チェックとか、トレース、ログの処理とか・・・
こーいうのは、どんなクラスにも(クラス横断的に)出てきてしまう、共通の事柄(=関心事)です。
っていうことで、横断的関心事と呼ばれ、これを切り出して、簡単に書けるようにしたのが、アスペクト指向なわけですが、このアスペクト指向のような、横断的関心事を、簡単に実装できちゃう機能が、モジュールです(って、モジュールが横断的関心事のためにでてきたのかは?だけど、まあ、そんなのにも、使えちゃうと思うわけですよ)
■moduleの使い方
で、そのmoduleの使い方なわけですが、
1.moduleで、メソッドを書きます。
2.それを、各クラスでincludeしちゃいます。
3.そーすると、各クラスで使えます。
こんなかんじ
module DebugModule def errorDisp(n) puts n end def traceDisp(n) puts n end end class ZZ include DebugModule attr_accessor :a def putme() traceDisp("putme in") puts @a end end |
(上記< > ¥は、本当は半角)
DebugModuleで、errorDispとtraceDispを宣言しています。
このメソッドが横断的関心事。
で、各クラス(といってもここではZZクラスしかないけど)で
include DebugModule
をします。
そうすると、DebugModuleの中にある、traceDispが使えます。
なので、ここで、
b=ZZ.new b.a = 1 b.putme |
とすると、
putme in
1
と、まずはじめのtraceDispの処理結果である、putme inが表示され、
そのあとに1と表示されます。
こんかいはここまで。