⚠️ Warning: This is a draft ⚠️

This means it might contain formatting issues, incorrect code, conceptual problems, or other severe issues.

If you want to help to improve and eventually enable this page, please fork RosettaGit's repository and open a merge request on GitHub.

==Manual Object System== Although [[C]] is not considered an OO language, you can do the following, which provides a semblance of an OO infrastructure allowing Inheritance and Polymorphism. The original [[C++]] was a front end which translated C++ code to C. (C++ was much simpler in those days.)"

/* Animal.h */
#ifndef _ANIMAL_H 
#define _ANIMAL_H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct object *Animal;

extern char *ObjSpeak(Animal a);
extern Animal ObjClone(Animal a);
extern void ObjDestroy(Animal a);
#endif
/* AnimalProt.h */
#include "Animal.h"
typedef struct sclass *Class;
typedef void (*CloneFctn)(Animal s, Animal clo);
typedef char * (*SpeakFctn)(Animal s);
typedef void (*DestroyFctn)(Animal s);
typedef void (*ClsRecInit)(Class c);

typedef struct object {
    Class class;
} SObject, *Object;

typedef struct sclass {
    size_t csize;		/* size of the class instance */
    char  *cname;		/* name of the class */
    Class  parent;		/* parent class */
    ClsRecInit crInit;          /* handle method inheritance for class record */

    CloneFctn clone;		/* clone function */
    SpeakFctn speak;		/* speak function */
    DestroyFctn del;		/* delete the object */
} sClass;

#define O_INHERIT (void *)-1
extern void ClassRecInit(Class c);
extern void DfltClsInit(Class c);
extern sClass boc;
/* Animal.c */
#include "AnimalProt.h"

static 
Animal obj_copy( Animal s, Class c )
{
    size_t size = s->class->csize;
    Animal clo;
    if (c->parent) 
        clo = obj_copy( s, c->parent);
    else {
        clo = (Animal )malloc( size );
        memcpy(clo, s, size);
    }

    if (clo)
        c->clone( s, clo );
    return clo;
}

static
void obj_del( Animal s, Class c )
{
    if (c->del)
        c->del(s);
    if (c->parent)
        obj_del( s, c->parent);
    else
        free(s);
}

Animal ObjClone( Animal s )
{ return obj_copy( s, s->class ); }

char * ObjSpeak( Animal s )
{ 
    return s->class->speak(s); 
}

void ObjDestroy( Animal s )
{ if (s) obj_del( s, s->class ); }

void ClassRecInit( Class c)
{
    if (c->crInit) {
        (*c->crInit)(c);
        c->crInit = NULL;
    }
}
static
void baseClsRecInit(Class c )
{
	if ((O_INHERIT == c->speak) && c->parent)
		c->speak = c->parent->speak;
}
void DfltClsInit(Class c)
{
	if (c->parent && c->parent->crInit) {
		ClassRecInit(c->parent);
	}
	printf("Initializing class %s\n", c->cname);
	baseClsRecInit(c);
}
/* * * * * * */
static
void baseClone( Animal s, Animal clone)
{  
    clone->class = s->class;
}

static
char *baseSpeak(Animal s)
{
    return "Hello, I'm an animal";
}

sClass boc = { sizeof(SObject), "Animal", NULL, &baseClsRecInit,
    &baseClone, &baseSpeak, NULL };
Class AnimalClass = &boc;
/* DogProt.h */
#include "AnimalProt.h"

typedef struct sDogPart {
    double weight;
    char color[32];
    char name[24];
} DogPart;

typedef struct sDog *Dog;

struct sDog {
    Class   class;			// parent structure
    DogPart dog;
};

extern void InitDog(DogPart *dogp, char *name, char *color, double weight);

extern sClass dogc;
/* Dog.c */
/** * * * * * * * * * * * * * * * * * *
 * Dog - a class derived from Animal 
 * * * * * * * * * * * * * * * * * * */
#include "DogProt.h"

static
void dogClone( Animal s, Animal c)
{  
    Dog src = (Dog)s;
    Dog clone = (Dog)c;
    clone->dog = src->dog;	/* no pointers so strncpys not needed */
}

static
char *dogSpeak( Animal 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, &DfltClsInit,
    &dogClone, &dogSpeak, NULL };
Class DogClass = &dogc;


void InitDog(DogPart *dogp, char *name, char *color, double weight)
{
    dogp->weight = weight;
    strncpy(dogp->name, name, 23);
    strncpy(dogp->color, color, 31);
}

Animal NewDog( char *name, char *color, double weight )
{
    Dog dog = (Dog)malloc(DogClass->csize);
    if (dog) {
        ClassRecInit(DogClass);
        dog->class = DogClass;
        InitDog(&dog->dog, name, color, weight);
    }
    return (Animal)dog;
}
/* Dog.h */
#ifndef _DOG_H
#define _DOG_H
#include "Animal.h"
extern Animal NewDog(char *name, char *color, double weight);
#endif
/* LabProt.h */
#include "DogProt.h"
/** * * * * * * * * * * * * * * * * * *
 * Lab - a class derived from Dog 
 * * * * * * * * * * * * * * * * * * */
typedef struct sLabPart {
    int  friendliness;
    int  tailIsWagging;	
} LabPart;

typedef struct sLab *Lab;

struct sLab {
    Class   class;			// parent structure
    DogPart dog;
    LabPart lab;			// my part
};

extern sClass labc;
/* Lab.c */
#include "LabProt.h"

void InitLab(LabPart *lab)
{
    lab->friendliness = 5;
    lab->tailIsWagging = 1;
}
static
void labClone( Animal s, Animal c)
{  
    Lab src = (Lab)s;
    Lab clone = (Lab)c;
    clone->lab = src->lab;
}

sClass labc = { sizeof(struct sLab), "Lab", &dogc, &DfltClsInit,
    &labClone, O_INHERIT, NULL };
Class LabClass = &labc;

Animal NewLab( char *name, char *color, double weight )
{
    Lab dog = (Lab)malloc(LabClass->csize);
    if (dog) {
        ClassRecInit(LabClass);
        dog->class = LabClass;
        InitDog( &dog->dog, name, color, weight);
        InitLab( &dog->lab);
    }
    return (Animal)dog;
}
/* Lab.h */
#include "Dog.h"
extern Animal NewLab(char *name, char *color, double weight);
/* CollieProt.h */
/** * * * * * * * * * * * * * * * * * *
 * Collie - a class derived from Dog 
 * * * * * * * * * * * * * * * * * * */
#include "DogProt.h"

typedef struct sColliePart {
    double  height;
} ColliePart;

typedef struct sCollie *Collie;

struct sCollie {
    Class   class;			// parent structure
    DogPart dog;
    ColliePart collie;			// my part
};

extern sClass colliec;
/* Collie.c */
#include "CollieProt.h"

static
void collieClone( Animal s, Animal c)
{  
    Collie src = (Collie)s;
    Collie clone = (Collie)c;
    clone->collie = src->collie;
}

void InitCollie(ColliePart *collie, double height)
{
    collie->height = 25.0;
}

sClass colliec = { sizeof(struct sCollie), "Collie", &dogc, &DfltClsInit,
    &collieClone, O_INHERIT, NULL };
Class CollieClass = &colliec;

Animal NewCollie( char *name, char *color, double weight, double height )
{
    Collie dog = (Collie)malloc(CollieClass->csize);
    if (dog) {
        ClassRecInit(CollieClass);
        dog->class = CollieClass;
        InitDog( &dog->dog, name, color, weight);
        InitCollie( &dog->collie, height);
    }
    return (Animal)dog;
}
/* Collie.h */
#include "Dog.h"
extern Animal NewCollie(char *name, char *color, double weight, double height);
/* CatProt.h */
#include "AnimalProt.h"
/* * * * * * * * * * * * */
/* Cat - a derived class */

typedef struct sCatPart {
    char color[32];
    char *name;
    int  age;
} CatPart;

typedef struct sCat *Cat;

struct sCat {
    Class   class;			// parent structure
    CatPart catpart;
};

extern sClass catcls;
/* Cat.c */
#include "CatProt.h"

static
void catClone( Animal s, Animal c)
{  
    Cat src = (Cat)s;
    Cat clone = (Cat)c;
    clone->catpart.name = strdup(src->catpart.name);
}

static
char *catSpeak(Animal s)
{
    Cat f = (Cat)s;
    static char  response[90];
    sprintf(response, "My name is %s. I'm a %d mo. old %s wiley %s", 
            f->catpart.name, f->catpart.age, f->catpart.color,
            f->class->cname);
    return response;
}

void catDel(Animal s)
{
    Cat f = (Cat)s;
    CatPart *catpart = &f->catpart;	
    if (catpart->name) {
        free(catpart->name);
    }
}

sClass catcls = { sizeof(struct sCat), "Cat", &boc, &DfltClsInit, 
    &catClone, &catSpeak, &catDel };
Class CatClass = &catcls;

Animal NewCat( char *name, char *color, int age )
{
    Cat cat = (Cat)malloc(CatClass->csize);
    if (cat) {
        CatPart *catpart = &(cat->catpart);
        ClassRecInit(CatClass);
        cat->class = CatClass;
        catpart->name = strdup(name);
        strncpy(catpart->color, color, 31);
        catpart->age = age;
    }
    return (Animal)cat;
}

/** * Now wasn' that fun. * **/
/* Cat.h */
#include "Animal.h"
extern Animal NewCat(char *name, char *color, int age);
#include "Cat.h"
#include "Lab.h"
#include "Collie.h"

int main(int argc, char *argv[])
{
    Animal  kara = NewCat( "Kara", "grey", 15 );
    Animal  bruce = NewDog("Bruce", "yellow", 85.0 );
    Animal  bigrex = NewLab("Rex", "chocolate", 65.0 );
    Animal  sandy = NewCollie("Sandy", "yellow", 35.0, 21.0 );
    printf("Ok, created pets\n");

    printf("Kara says %s\n", ObjSpeak(kara));
    printf("Bruce says %s\n", ObjSpeak(bruce));
    printf("Big Rex says %s\n", ObjSpeak(bigrex));
    printf("Sandy says %s\n", ObjSpeak(sandy));
    ObjDestroy(kara);
    ObjDestroy(bruce);
    ObjDestroy(bigrex);
    ObjDestroy(sandy);

    return 0;
}