Polymorphic copy: Difference between revisions

Added C
(→‎{{header|Tcl}}: Implement an object cloning demonstration)
(Added C)
Line 57:
</pre>
 
=={{header|C}}==
Since C doesn't support classes, this is not quite so trivial. Normally the code below
would be split into a number of files. Specificially there would be a header (.h) file and
a source (.c) file for each of - BaseObj, Dog, and Ferret. The code in "main" would also be
a separate source file which would include Dog.h and Ferret.h header files (which would thems
elves include the BaseObj.h header file.) A better example of object oriented support in 'C' can
be found in the source for the XtIntrinsics library of X11.
<lang c>#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
typedef struct object *BaseObj;
typedef struct sclass *Class;
typedef void (*CloneFctn)(BaseObj s, BaseObj clo);
typedef char * (*SpeakFctn)(BaseObj s);
typedef void (*DestroyFctn)(BaseObj s);
 
typedef struct sclass {
size_t csize; /* size of the class instance */
char *cname; /* name of the class */
Class parent; /* parent class */
 
CloneFctn clone; /* clone function */
SpeakFctn speak; /* speak function */
DestroyFctn del; /* delete the object */
} sClass;
 
typedef struct object {
Class class;
} SObject;
 
static
BaseObj obj_copy( BaseObj s, Class c )
{
BaseObj clo;
if (c->parent)
clo = obj_copy( s, c->parent);
else
clo = (BaseObj )malloc( s->class->csize );
 
if (clo)
c->clone( s, clo );
return clo;
}
 
static
void obj_del( BaseObj s, Class c )
{
if (c->del)
c->del(s);
if (c->parent)
obj_del( s, c->parent);
else
free(s);
}
 
BaseObj ObjClone( BaseObj s )
{ return obj_copy( s, s->class ); }
 
char * ObjSpeak( BaseObj s )
{
return s->class->speak(s);
}
 
void ObjDestroy( BaseObj s )
{ if (s) obj_del( s, s->class ); }
 
/* * * * * * */
static
void baseClone( BaseObj s, BaseObj clone)
{
clone->class = s->class;
}
 
static
char *baseSpeak(BaseObj s)
{
return "Hello, I'm base object";
}
 
sClass boc = { sizeof(SObject), "BaseObj", NULL,
&baseClone, &baseSpeak, NULL };
Class BaseObjClass = &boc;
 
/* * * * * * */
/* Dog - a derived class */
 
typedef struct sDogPart {
double weight;
char color[32];
char name[24];
} DogPart;
 
typedef struct sDog *Dog;
 
struct sDog {
Class class; // parent structure
DogPart dog;
};
 
static
void dogClone( BaseObj s, BaseObj c)
{
Dog src = (Dog)s;
Dog clone = (Dog)c;
clone->dog = src->dog; /* no pointers so strncpys not needed */
}
 
static
char *dogSpeak( BaseObj s)
{
Dog d = (Dog)s;
static char response[90];
sprintf(response, "woof! woof! My name is %s. I'm a %s %s",
d->dog.name, d->dog.color, d->class->cname);
return response;
}
 
 
sClass dogc = { sizeof(struct sDog), "Dog", &boc,
&dogClone, &dogSpeak, NULL };
Class DogClass = &dogc;
 
BaseObj NewDog( char *name, char *color, double weight )
{
Dog dog = (Dog)malloc(DogClass->csize);
if (dog) {
DogPart *dogp = &dog->dog;
dog->class = DogClass;
dogp->weight = weight;
strncpy(dogp->name, name, 23);
strncpy(dogp->color, color, 31);
}
return (BaseObj)dog;
}
 
/* * * * * * * * * */
/* Ferret - a derived class */
 
typedef struct sFerretPart {
char color[32];
char name[24];
int age;
} FerretPart;
 
typedef struct sFerret *Ferret;
 
struct sFerret {
Class class; // parent structure
FerretPart ferret;
};
 
static
void ferretClone( BaseObj s, BaseObj c)
{
Ferret src = (Ferret)s;
Ferret clone = (Ferret)c;
clone->ferret = src->ferret; /* no pointers so strncpys not needed */
}
 
static
char *ferretSpeak(BaseObj s)
{
Ferret f = (Ferret)s;
static char response[90];
sprintf(response, "My name is %s. I'm a %d mo. old %s wiley %s",
f->ferret.name, f->ferret.age, f->ferret.color,
f->class->cname);
return response;
}
 
sClass ferretc = { sizeof(struct sFerret), "Ferret", &boc,
&ferretClone, &ferretSpeak, NULL };
Class FerretClass = &ferretc;
 
BaseObj NewFerret( char *name, char *color, int age )
{
Ferret ferret = (Ferret)malloc(FerretClass->csize);
if (ferret) {
FerretPart *ferretp = &(ferret->ferret);
ferret->class = FerretClass;
strncpy(ferretp->name, name, 23);
strncpy(ferretp->color, color, 31);
ferretp->age = age;
}
return (BaseObj)ferret;
}
 
/* * Now you really understand why Bjarne created C++ * */
 
int main(int argc, char *argv[])
{
BaseObj o1;
BaseObj kara = NewFerret( "Kara", "grey", 15 );
BaseObj bruce = NewDog("Bruce", "yellow", 85.0 );
printf("Ok created things\n");
 
o1 = ObjClone(kara );
printf("Karol says %s\n", ObjSpeak(o1));
printf("Kara says %s\n", ObjSpeak(kara));
ObjDestroy(o1);
 
o1 = ObjClone(bruce );
strncpy(((Dog)o1)->dog.name, "Donald", 23);
printf("Don says %s\n", ObjSpeak(o1));
printf("Bruce says %s\n", ObjSpeak(bruce));
ObjDestroy(o1);
return 0;
}</lang>
=={{header|C++}}==
<lang cpp>#include <iostream>
Anonymous user