C - Better abstraction and encapsulation than the others
I'm not satisfied with the versions in C that I've seen. We should use an abstract typedef and private struct thusly:
fraction.h
#ifndef FRACTION_H
#define FRACTION_H
#ifdef __cplusplus
extern "C" {
#endif
struct Fraction_private;
typedef struct Fraction_private Fraction;
Fraction *FractionCreate(int numerator, int denominator);
void FractionDestroy(Fraction *fraction);
int FractionGetNumerator(Fraction *fraction);
int FractionGetDenominator(Fraction *fraction);
void FractionPrint(Fraction *fraction);
#ifdef __cplusplus
} // extern
#endif
#endif
fraction.c
#include "fraction.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
struct Fraction_private {
int numerator;
int denominator;
};
Fraction *FractionCreate(int numerator, int denominator) {
Fraction *result = malloc(sizeof(*result));
result->numerator = numerator;
result->denominator = denominator;
return result;
}
void FractionDestroy(Fraction *fraction) {
free(fraction);
}
int FractionGetNumerator(Fraction *fraction) {
assert(fraction);
return fraction->numerator;
}
int FractionGetDenominator(Fraction *fraction) {
assert(fraction);
return fraction->denominator;
}
void FractionPrint(Fraction *fraction) {
assert(fraction);
printf("%d/%d", fraction->numerator, fraction->denominator);
}
Example use:
#include "fraction.h"
#include <stdio.h>
int main() {
Fraction *f = FractionCreate(2, 4);
printf("Numerator is %d, denominator is %d\n",
FractionGetNumerator(f),
FractionGetDenominator(f));
printf("Using the print function: ");
FractionPrint(f);
printf("\n");
FractionDestroy(f);
return 0;
}
Now this looks much cleaner and abstract doesn't it? In fact, when you get down to it, this C is very much like object-oriented languages, just with a different syntax. Private members are inaccessible, and we can only manipulate the type using the predefined functions. We just happen to pass an explicit 'this' argument to each function.
Of course, in a real application a datatype this simple would probably be implemented as a struct on the stack like other solutions have done. But I though this would be nice for people to see that C can in fact do some nice abstract types.