2026-10-02 00:08:18 +02:00
|
|
|
/*
|
|
|
|
|
* This file is part of libooc.
|
|
|
|
|
* https://xw3.org/hanez/libooc
|
|
|
|
|
*
|
|
|
|
|
* Copyright 2026 Johannes Findeisen <you@hanez.org>
|
|
|
|
|
* Licensed under the terms of the Apache-2.0 license.
|
|
|
|
|
* https://opensource.org/license/apache-2.0
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef CAT_H
|
|
|
|
|
#define CAT_H
|
|
|
|
|
|
|
|
|
|
#include "animal.h"
|
|
|
|
|
|
|
|
|
|
typedef struct Cat Cat;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Derived class.
|
|
|
|
|
*
|
|
|
|
|
* The embedded Animal comes first, so a Cat pointer can be handed to any
|
|
|
|
|
* function expecting an Animal, and Cat adds a colour and a private `_lives` of
|
|
|
|
|
* its own.
|
|
|
|
|
*
|
|
|
|
|
* Two things follow from that ordering. The ooc_object header inside Animal
|
|
|
|
|
* stays at offset zero, where the library looks for it, and the upcast is a
|
|
|
|
|
* no-op cast because both addresses are the same -- which is what lets speak()
|
|
|
|
|
* in cat.c cast its Animal * back to a Cat * without arithmetic. The cost is
|
|
|
|
|
* that a Cat may not add a member of its own before the base.
|
|
|
|
|
*
|
|
|
|
|
* The struct holds no destructor of its own; the one Cat registers lives in
|
|
|
|
|
* Cat_class and releases both the colour and Animal's name.
|
|
|
|
|
*/
|
|
|
|
|
struct Cat {
|
|
|
|
|
Animal animal;
|
2026-10-02 00:33:43 +02:00
|
|
|
char *colour;
|
2026-10-02 00:08:18 +02:00
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Private to Cat, and readable by name: one leading underscore stops
|
|
|
|
|
* ooc_set() from writing it but leaves ooc_get() alone. Animal's `_id` works
|
|
|
|
|
* the same way, so the rule is the one in the library rather than something
|
|
|
|
|
* the subclass has to repeat.
|
|
|
|
|
*/
|
2026-10-02 00:33:43 +02:00
|
|
|
int _lives;
|
2026-10-02 00:08:18 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Cat's runtime type record, the value ooc_new() takes.
|
|
|
|
|
*
|
|
|
|
|
* Its `super` is Animal_class, so a Cat inherits Animal's fields, and its
|
|
|
|
|
* `size` is sizeof(Cat), so the allocation has room for the colour and the
|
|
|
|
|
* lives count.
|
|
|
|
|
*/
|
|
|
|
|
extern const ooc_class Cat_class;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Create a Cat named `name` of the given `colour` and return it, or NULL.
|
|
|
|
|
*
|
|
|
|
|
* The result has a reference count of one, so ownership is the caller's and it
|
|
|
|
|
* must reach ooc_release() eventually. Returns NULL if any step of the
|
|
|
|
|
* construction fails, leaving nothing to release.
|
|
|
|
|
*
|
|
|
|
|
* The object is a Cat and answers to Cat's `speak`, whether it is later reached
|
|
|
|
|
* through a Cat * or an Animal *.
|
|
|
|
|
*/
|
|
|
|
|
Cat *cat_new(const char *name, int age, const char *colour);
|
|
|
|
|
|
|
|
|
|
#endif /* CAT_H */
|