『Java 謎+落とし穴 徹底解明』 3.3 寄り道 - Cで継承を実現してみる
p.177 - List 3.11 - 3.22 について、 たとえば ExtendedPolyline を追加す
るとしたらどうするのか、つたないながら考えてみました。
ここのところいろいろご面倒をおかけしておりますが、またよろしければご叱
正いただけると幸いです。
(なお、
http://kmaebashi.com/programmer/c_yota/inherit.html
も拝見しましたが、申し訳ないことにいまのわたしには難解でした。)
まず、 Shape.c の MethodTableIndex を Shape.h に移動するのはまずいでしょ
うか。しかし、そうしたとして、あとは以下のファイルを改変または追加しました。
(なお、 Shape は abstract 相当と理解しております。)
---- Polyline.h -----------------------------------------
#ifndef POLYLINE_H_INCLUDED
#define POLYLINE_H_INCLUDED
#include "Shape.h"
#include "Point2D.h"
typedef struct {
Shape super;
int nPoints;
Point2D *point;
} Polyline;
Polyline *createPolyline(void);
void drawPolyline(Polyline *polyline);
ClassDescriptor *getPolylineClassDescriptor(void);
#endif /* POLYLINE_H_INCLUDED */
---- Polyline.c -----------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include "Polyline.h"
static void drawPolylineImpl(void);
static void (*methodTable[])() = {
drawPolylineImpl
};
static ClassDescriptor polylineClassDescriptor = {
methodTable
};
ClassDescriptor *getPolylineClassDescriptor(void) {
return &polylineClassDescriptor;
}
Polyline *createPolyline(void)
{
Polyline *p = malloc(sizeof(Polyline));
p->super.super.classDescriptor = &polylineClassDescriptor;
p->nPoints = 0;
p->point = NULL;
return p;
}
void drawPolyline(Polyline *polyline)
{
polyline->super.super.classDescriptor->methodTable[(int)DRAW_INDEX]();
}
static void drawPolylineImpl(void)
{
fprintf(stderr, "Polylineを描画\n");
}
---- ExtendedPolyline.h ---------------------------------
#ifndef EXTENDED_POLYLINE_H_INCLUDED
#define EXTENDED_POLYLINE_H_INCLUDED
#include "Polyline.h"
#include "Point2D.h"
typedef struct {
Polyline super;
int nPoints;
Point2D *point;
} ExtendedPolyline;
ExtendedPolyline *createExtendedPolyline(void);
void drawExtendedPolyline(ExtendedPolyline *extendedPolyline);
#endif /* EXTENDED_POLYLINE_H_INCLUDED */
---- ExtendedPolyline.c ---------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include "ExtendedPolyline.h"
static void drawExtendedPolylineImpl(void);
static void (*methodTable[])() = {};
static ClassDescriptor extendedPolylineClassDescriptor = {
methodTable
};
/* このへんがとりわけリアリティにかけるのかも…… */
void initExtendedPolyline(void) {
ClassDescriptor *cd = getPolylineClassDescriptor();
void (**mt)() = cd->methodTable;
memcpy(methodTable, mt, sizeof(mt));
methodTable[(int)DRAW_INDEX] = drawExtendedPolylineImpl;
}
ExtendedPolyline *createExtendedPolyline(void)
{
ExtendedPolyline *ep = malloc(sizeof(ExtendedPolyline));
/*
http://kmaebashi.com/programmer/c_yota/inherit.html
には super.super.super.... を回避する裏技が紹介されていますが……
*/
ep->super.super.super.classDescriptor = &extendedPolylineClassDescriptor;
ep->nPoints = 0;
ep->point = NULL;
return ep;
}
void drawExtendedPolyline(ExtendedPolyline *extendedPolyline)
{
extendedPolyline->super.super.super.classDescriptor->methodTable[(int)DRAW_INDEX]();
}
static void drawExtendedPolylineImpl(void)
{
fprintf(stderr, "ExtendedPolylineを描画\n");
}
---- draw.h ---------------------------------------------
#include "Shape.h"
void draw(Shape **shapes);
---- draw.c ---------------------------------------------
/*
http://kmaebashi.com/bbs/thread.php?boardid=kmaebashibbs&from=1906&range=1
*/
#include <stdio.h>
#include "Shape.h"
void draw(Shape **shapes)
{
int i;
for (i = 0; i < 4; i++) {
drawShape(shapes[i]);
}
}
---- main.c ---------------------------------------------
#include <stdio.h>
#include "Shape.h"
#include "Polyline.h"
#include "Circle.h"
#include "Rectangle.h"
#include "ExtendedPolyline.h"
#include "draw.h"
int main(void)
{
Shape *shapes[4];
int i;
initExtendedPolyline();
shapes[0] = (Shape*)createPolyline();
shapes[1] = (Shape*)createCircle();
shapes[2] = (Shape*)createRectangle();
shapes[3] = (Shape*)createExtendedPolyline();
draw(shapes);
printf("\n");
drawPolyline(createPolyline());
drawPolyline((Polyline*)createExtendedPolyline());
drawExtendedPolyline(createExtendedPolyline());
return 0;
}
---------------------------------------------------------