OOP can be done using the Gobject library. The programming language Vala uses GObject to implement OOP.
The Vala compiler turns Vala code into C (and gcc turns the generated C code into an executable).
I'll give an example of Vala code and the C code generated by the Vala compiler.
Input (Vala)
Code: Select all
class Person : Object {
private int _age = 32; // underscore prefix to avoid name clash with property
/* Property */
public int age {
get { return _age; }
set { _age = value; }
}
}
void main()
{
var my_person = new Person();
my_person.age = 23;
}
Output (C)
Code: Select all
/* class.c generated by valac, the Vala compiler
* generated from class.vala, do not modify */
#include <glib.h>
#include <glib-object.h>
#define TYPE_PERSON (person_get_type ())
#define PERSON(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TYPE_PERSON, Person))
#define PERSON_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TYPE_PERSON, PersonClass))
#define IS_PERSON(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TYPE_PERSON))
#define IS_PERSON_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TYPE_PERSON))
#define PERSON_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TYPE_PERSON, PersonClass))
typedef struct _Person Person;
typedef struct _PersonClass PersonClass;
typedef struct _PersonPrivate PersonPrivate;
#define _g_object_unref0(var) ((var == NULL) ? NULL : (var = (g_object_unref (var), NULL)))
struct _Person {
GObject parent_instance;
PersonPrivate * priv;
};
struct _PersonClass {
GObjectClass parent_class;
};
struct _PersonPrivate {
gint _age;
};
static gpointer person_parent_class = NULL;
GType person_get_type (void) G_GNUC_CONST;
#define PERSON_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TYPE_PERSON, PersonPrivate))
enum {
PERSON_DUMMY_PROPERTY,
PERSON_AGE
};
Person* person_new (void);
Person* person_construct (GType object_type);
gint person_get_age (Person* self);
void person_set_age (Person* self, gint value);
static void person_finalize (GObject* obj);
static void person_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
static void person_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec);
void _vala_main (void);
Person* person_construct (GType object_type) {
Person * self;
self = (Person*) g_object_new (object_type, NULL);
return self;
}
Person* person_new (void) {
return person_construct (TYPE_PERSON);
}
gint person_get_age (Person* self) {
gint result;
g_return_val_if_fail (self != NULL, 0);
result = self->priv->_age;
return result;
}
void person_set_age (Person* self, gint value) {
g_return_if_fail (self != NULL);
self->priv->_age = value;
g_object_notify ((GObject *) self, "age");
}
static void person_class_init (PersonClass * klass) {
person_parent_class = g_type_class_peek_parent (klass);
g_type_class_add_private (klass, sizeof (PersonPrivate));
G_OBJECT_CLASS (klass)->get_property = person_get_property;
G_OBJECT_CLASS (klass)->set_property = person_set_property;
G_OBJECT_CLASS (klass)->finalize = person_finalize;
g_object_class_install_property (G_OBJECT_CLASS (klass), PERSON_AGE, g_param_spec_int ("age", "age", "age", G_MININT, G_MAXINT, 0, G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | G_PARAM_STATIC_BLURB | G_PARAM_READABLE | G_PARAM_WRITABLE));
}
static void person_instance_init (Person * self) {
self->priv = PERSON_GET_PRIVATE (self);
self->priv->_age = 32;
}
static void person_finalize (GObject* obj) {
Person * self;
self = PERSON (obj);
G_OBJECT_CLASS (person_parent_class)->finalize (obj);
}
GType person_get_type (void) {
static volatile gsize person_type_id__volatile = 0;
if (g_once_init_enter (&person_type_id__volatile)) {
static const GTypeInfo g_define_type_info = { sizeof (PersonClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, (GClassInitFunc) person_class_init, (GClassFinalizeFunc) NULL, NULL, sizeof (Person), 0, (GInstanceInitFunc) person_instance_init, NULL };
GType person_type_id;
person_type_id = g_type_register_static (G_TYPE_OBJECT, "Person", &g_define_type_info, 0);
g_once_init_leave (&person_type_id__volatile, person_type_id);
}
return person_type_id__volatile;
}
static void person_get_property (GObject * object, guint property_id, GValue * value, GParamSpec * pspec) {
Person * self;
self = PERSON (object);
switch (property_id) {
case PERSON_AGE:
g_value_set_int (value, person_get_age (self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void person_set_property (GObject * object, guint property_id, const GValue * value, GParamSpec * pspec) {
Person * self;
self = PERSON (object);
switch (property_id) {
case PERSON_AGE:
person_set_age (self, g_value_get_int (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
void _vala_main (void) {
Person* my_person;
my_person = person_new ();
person_set_age (my_person, 23);
_g_object_unref0 (my_person);
}
int main (int argc, char ** argv) {
g_type_init ();
_vala_main ();
return 0;
}
That's 15 lines of code written in a language that looks a bit like C translated into over 150 lines of C code.
You could use FreeBASIC in combination with the GObject library to get some kind of OOP going.