さくっと基本を振り返る3
継承についても考えてみる。
またも Wikipedia 先生
あるオブジェクトが他のオブジェクトの特性を引き継ぐ場合、両者の間に「継承関係」があると言われる。
とのこと。
メソッドの動作や変数やパラメータを受け継ぐわけですな、具象化の話まで行くとポリモーフィズムな話になるので割愛と。
Java でも C# でも Objective-C にもあるにはあるな。
class Fluit { protected float sugarContent; public getSugarContent() { return this.sugarContent; } public setSugarContent(float contentvalue) { this.sugarContent = contentvalue; } } class Banana extends Fluit { /* 略 */ }
糖度というパラメータをフルーツに持たせて、それを継承しているバナナにも、糖度というパラメータがある。
継承は Objective-C では以下の書き方になる。
// Fluits.h #import <Cocoa/Cocoa.h> @interface Fluits : NSObject { float sugarContent; } @property float sugarContent; @end // Fluits.m #import "Fluits.h" @implementation Fluits @synthesize sugarContent; @end
// Banana.h #import <Cocoa/Cocoa.h> #import "Fluits.h" @interface Banana : Fluits { } /* メソッドとか */ @end // Banana.m #import "Banana.h" @implementation Banana /* メソッドとか */ @end
やっとる事はかわりません。書き方の問題で、食いやすい食いにくいかの問題。
多態性を持つための継承は Objective-C だとほとんど不要なので、ここでの継承は文字通り属性の引き継ぎ位の意味しか持たない。
加えて言えば機能の拡張も Objective-C では継承不要だ(属性の拡張はできないので注意)。これには、言語仕様のカテゴリというものを利用する。
例えば、乱暴な例ではあるが、Fluits クラスを拡張してみる。Fluits の糖度が 15 以上なら食べごろだと判定するメソッドを拡張する。
// FluitsExtention.h #import <Cocoa/Cocoa.h> #import "Fluits.h" @interface Fluits <GoodForEat> - (BOOL) isGoodForEat; @end // FluitsExtention.m #import "FluitsExtention.h" @implementation Fluits <GoodForEat> - (BOOL) isGoodForEat { return sugarContent > 15.0f; } @end // 利用例 id fluits = [Banana alloc]; BOOL isgood = [fluits isGoodForEat];
素敵。
既に継承されていようが、コンパイル済みで、ライブラリになってるオブジェクトだろうが関係なしに拡張できる。
C# 3.0 では、拡張メソッドという機能でこれが実現できる。
public static class Fluits { public static bool isGoodForEat(this Fluits target) { return target.sugarContent > 15.0f; } } // 利用例 Banana banana = new Banana(); bool isgood = banana.isGoodForEat();
C# の場合、オブジェクトの protected/private なフィールドにはアクセスできない。あくまで補助メソッドの追加程度だ(string 拡張に CSV パース機能入れるとか、メソッドの外でもできる事)。
Java 1.6 までの段階では確かできない筈だ(通常のアプローチでは)。最も、Java の場合は、中間コードに落ちるので、その仕様を知っていれば class ファイルに介入してできなくは無さそう。カバレッジツールの一部でそんな事をやってた記憶がある。
僕はその辺は知らないので JavaHacker の方何方かよろしく!