diff options
author | Andreas Färber <afaerber@suse.de> | 2013-01-17 08:31:50 +0100 |
---|---|---|
committer | Anthony Liguori <aliguori@us.ibm.com> | 2013-01-17 07:33:16 -0600 |
commit | 782beb5239c6306b166744e03478a75afb649811 (patch) | |
tree | 7c654901074e8ac842cc469ad136265d5c6e551a /include | |
parent | 781c0c3321d2bda9a9d7ffe9bf51560f0987b5a0 (diff) |
qom: Extend documentation on QOM method concepts
Add a documentation section "Methods" and discuss among others how to
handle overriding virtual methods.
Clarify DeviceClass::realize documentation and refer to the above.
Signed-off-by: Andreas Färber <afaerber@suse.de>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/qom/object.h | 104 |
1 files changed, 101 insertions, 3 deletions
diff --git a/include/qom/object.h b/include/qom/object.h index 1ef2f0edd4..8e16ea8a44 100644 --- a/include/qom/object.h +++ b/include/qom/object.h @@ -147,9 +147,9 @@ typedef struct InterfaceInfo InterfaceInfo; * </programlisting> * </example> * - * Introducing new virtual functions requires a class to define its own - * struct and to add a .class_size member to the TypeInfo. Each function - * will also have a wrapper to call it easily: + * Introducing new virtual methods requires a class to define its own + * struct and to add a .class_size member to the #TypeInfo. Each method + * will also have a wrapper function to call it easily: * * <example> * <title>Defining an abstract class</title> @@ -186,6 +186,104 @@ typedef struct InterfaceInfo InterfaceInfo; * similar to normal types except for the fact that are only defined by * their classes and never carry any state. You can dynamically cast an object * to one of its #Interface types and vice versa. + * + * # Methods # + * + * A <emphasis>method</emphasis> is a function within the namespace scope of + * a class. It usually operates on the object instance by passing it as a + * strongly-typed first argument. + * If it does not operate on an object instance, it is dubbed + * <emphasis>class method</emphasis>. + * + * Methods cannot be overloaded. That is, the #ObjectClass and method name + * uniquely identity the function to be called; the signature does not vary + * except for trailing varargs. + * + * Methods are always <emphasis>virtual</emphasis>. Overriding a method in + * #TypeInfo.class_init of a subclass leads to any user of the class obtained + * via OBJECT_GET_CLASS() accessing the overridden function. + * The original function is not automatically invoked. It is the responsability + * of the overriding class to determine whether and when to invoke the method + * being overridden. + * + * To invoke the method being overridden, the preferred solution is to store + * the original value in the overriding class before overriding the method. + * This corresponds to |[ {super,base}.method(...) ]| in Java and C# + * respectively; this frees the overriding class from hardcoding its parent + * class, which someone might choose to change at some point. + * + * <example> + * <title>Overriding a virtual method</title> + * <programlisting> + * typedef struct MyState MyState; + * + * typedef void (*MyDoSomething)(MyState *obj); + * + * typedef struct MyClass { + * ObjectClass parent_class; + * + * MyDoSomething do_something; + * } MyClass; + * + * static void my_do_something(MyState *obj) + * { + * // do something + * } + * + * static void my_class_init(ObjectClass *oc, void *data) + * { + * MyClass *mc = MY_CLASS(oc); + * + * mc->do_something = my_do_something; + * } + * + * static const TypeInfo my_type_info = { + * .name = TYPE_MY, + * .parent = TYPE_OBJECT, + * .instance_size = sizeof(MyState), + * .class_size = sizeof(MyClass), + * .class_init = my_class_init, + * }; + * + * typedef struct DerivedClass { + * MyClass parent_class; + * + * MyDoSomething parent_do_something; + * } MyClass; + * + * static void derived_do_something(MyState *obj) + * { + * DerivedClass *dc = DERIVED_GET_CLASS(obj); + * + * // do something here + * dc->parent_do_something(obj); + * // do something else here + * } + * + * static void derived_class_init(ObjectClass *oc, void *data) + * { + * MyClass *mc = MY_CLASS(oc); + * DerivedClass *dc = DERIVED_CLASS(oc); + * + * dc->parent_do_something = mc->do_something; + * mc->do_something = derived_do_something; + * } + * + * static const TypeInfo derived_type_info = { + * .name = TYPE_DERIVED, + * .parent = TYPE_MY, + * .class_size = sizeof(DerivedClass), + * .class_init = my_class_init, + * }; + * </programlisting> + * </example> + * + * Alternatively, object_class_by_name() can be used to obtain the class and + * its non-overridden methods for a specific type. This would correspond to + * |[ MyClass::method(...) ]| in C++. + * + * The first example of such a QOM method was #CPUClass.reset, + * another example is #DeviceClass.realize. */ |