Integerクラスのサブクラス LoggableIntegerクラスには、スーパクラスの getValue関数をオーバライドする。この関数は Integerのそれど同様 int型の値を返すが、この関数を呼び出した回数を変数 counterに記録し、getAccessCount関数で読み出せるようにする。
ヘッダファイル (header file)
LoggableInteger.hはつぎの通り。/* 13.Aug.2012 kei */
#ifndef _Included_LoggableInteger
#define _Included_LoggableInteger
typedef struct LoggableInteger* LoggableInteger;
typedef struct interface_LoggableInteger {
void (*finalize)(LoggableInteger this);
int (*getValue)(LoggableInteger this);
int (*getAccessCount)(LoggableInteger this);
}* interface_LoggableInteger;
extern void static_LoggableInteger(interface_LoggableInteger interface_methods);
extern LoggableInteger new_LoggableInteger(int value);
extern void LoggableInteger_init(LoggableInteger this, int value);
extern void LoggableInteger_finalize(LoggableInteger this);
extern int LoggableInteger_getValue(LoggableInteger this);
extern int LoggableInteger_getAccessCount(LoggableInteger this);
#endif /* _Included_LoggableInteger */
変数や関数が違う点以外は IntegerValueクラスのヘッダと同様。
ソースファイル (source file)
LoggableInteger.cはつぎの通り。/* 13.Aug.2012 kei */
#include <LoggableInteger.h>
#include <Integer.h>
/****************************************************************
private
****************************************************************/
#include <malloc.h>
struct LoggableInteger {
interface_LoggableInteger interface_methods;
/* Integer class */
int value;
/* LoggaableInteger class */
int counter;
};
static struct interface_LoggableInteger interface_methods;
static struct interface_Integer super;
static int getValue(LoggableInteger this) {
++this->counter;
return Integer_getValue((Integer)this);
}
static int getAccessCount(LoggableInteger this) {
return this->counter;
}
/****************************************************************
public
****************************************************************/
void static_LoggableInteger(interface_LoggableInteger interface_methods) {
/* ToDo: lock interface_methods */
if (interface_methods->finalize == NULL) {
static_Integer(&super);
static_Integer((interface_Integer)interface_methods);
interface_methods->getValue = getValue;
interface_methods->getAccessCount = getAccessCount;
}
}
LoggableInteger new_LoggableInteger(int value) {
static_LoggableInteger(&interface_methods);
LoggableInteger this =
(LoggableInteger)malloc(sizeof(struct LoggableInteger));
if (this != NULL)
LoggableInteger_init(this, value);
return this;
}
void LoggableInteger_init(LoggableInteger this, int value) {
Integer_init((Integer)this, value);
this->interface_methods = &interface_methods;
}
void LoggableInteger_finalize(LoggableInteger this) {
this->interface_methods->finalize(this);
}
int LoggableInteger_getValue(LoggableInteger this) {
return this->interface_methods->getValue(this);
}
int LoggableInteger_getAccessCount(LoggableInteger this) {
return this->interface_methods->getAccessCount(this);
}
これも IntegerVariableクラスとほぼ同じだが、getValue関数をオーバライドするため、LoggableIntegerクラスで改めて定義し、static_LoggableIntegerで getValue関数を設定している。
static_Integer関数を呼び出した時点で、interface_methodsには一旦スーパクラスの getValue関数が設定される。その後でサブクラスの関数を上書きしている。 概念だけでなく実際に上書きしているので、如何にも "override"の感じがする。
関数テーブルは interface_methodsのほかに Integerクラス用の superも定義している。
これは、Integerクラスの getValueを呼び出すために必要となる。
getValue関数の中では、 super.getValue((Integer)this); を呼び出すことにより、スーパクラスの取得関数を利用している。
動作確認 (unit test)
テストケース LoggableIntegerTest.cはつぎの通り。/* 14.Aug.2012 kei */
#define import_lwd_unit_Assert
#define import_lwd_unit_CUnit
#include <lwd/unit/Assert.h>
#include <lwd/unit/CUnit.h>
#include <LoggableInteger.h>
/****************************************************************
test cases
****************************************************************/
static LoggableInteger instance;
void setUp() {
instance = new_LoggableInteger(813);
}
void tearDown() {
LoggableInteger_finalize(instance);
}
void testNewAndFinalize() {
/* setUp, tearDown */
}
void testGetValue() {
int value = LoggableInteger_getValue(instance);
Assert_equalsInt("A value must be 813.", 813, value);
}
void testGetAccessCount() {
Assert_equalsInt("must be zero.",
0, LoggableInteger_getAccessCount(instance));
LoggableInteger_getValue(instance);
Assert_equalsInt("must be 1.",
1, LoggableInteger_getAccessCount(instance));
}
/****************************************************************
main
****************************************************************/
int main(int argc, char** argv) {
return CUnit_test(argc, argv);
}
テストのビルドと実行結果も残しておく。
$ make cc -g -finstrument-functions -I. -I /export/home/kei/c/core/include -I /export/home/ kei/c/experimental/include -I /export/home/kei/c/io/include -I /export/home/kei/c/lang /include -I /export/home/kei/c/message/include -I /export/home/kei/c/unit/include -I /export/home/kei/c/util/include -I /export/home/kei/c/x11/include -I ../../char/ include -I ../../class1/include -c -o LoggableIntegerTest.o LoggableIntegerTest.c $ ./LoggableIntegerTest [CUnit] ./LoggableIntegerTest: testGetAccessCount [CUnit] ./LoggableIntegerTest: testGetValue [CUnit] ./LoggableIntegerTest: testNewAndFinalize [SUCCEED] testGetAccessCount in 1(ms) [SUCCEED] testGetValue in 2(ms) [SUCCEED] testNewAndFinalize in 2(ms) successes: 3 (100.0%) failures: 0 (0.0%) errors: 0 (0.0%) total: 3 in 5(ms) $
竜巻情報が出された。豹が降る恐れがあるとか言っている。

0 件のコメント:
コメントを投稿