[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    KDE/kdelibs/phonon
From:       Matthias Kretz <kretz () kde ! org>
Date:       2008-02-29 23:39:58
Message-ID: 1204328398.590625.20420.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 780776 by mkretz:

add dox for internal Iface class

 M  +85 -0     phonondefs_p.h  


--- trunk/KDE/kdelibs/phonon/phonondefs_p.h #780775:780776
@@ -176,6 +176,91 @@
 
     } // anonymous namespace
 
+    /**
+     * \internal
+     *
+     * \brief Helper class to cast the backend object to the correct version of the interface.
+     *
+     * Additions to the backend interfaces cannot be done by adding virtual methods as that would
+     * break the binary interface. So the old class is renamed and a new class with the old name
+     * inheriting the old class is added, containing all the new virtual methods.
+     * Example:
+     * \code
+       class FooInterface
+       {
+       public:
+           virtual ~FooInterface() {}
+           virtual oldMethod() = 0;
+       };
+       Q_DECLARE_INTERFACE(FooInterface, "FooInterface0.phonon.kde.org")
+     * \endcode
+     * becomes
+     * \code
+       class FooInterface0
+       {
+       public:
+           virtual ~FooInterface0() {}
+           virtual oldMethod() = 0;
+       };
+       class FooInterface : public FooInterface0
+       {
+       public:
+           virtual newMethod() = 0;
+       };
+       Q_DECLARE_INTERFACE(FooInterface0, "FooInterface0.phonon.kde.org")
+       Q_DECLARE_INTERFACE(FooInterface,  "FooInterface1.phonon.kde.org")
+     * \endcode
+     *
+     * With this, backends compiled against the old header can be qobject_casted to FooInterface0,
+     * but not to FooInterface. On the other hand backends compiled against the new header (they first
+     * need to implement newMethod) can only be qobject_casted to FooInterface but not to
+     * FooInterface0. (The qobject_cast relies on the string in Q_DECLARE_INTERFACE and not the
+     * class name which is why it behaves that way.)
+     *
+     * Now, in order to call oldMethod, the code needs to try to cast to both FooInterface and
+     * FooInterface0 (new backends will work with the former, old backends with the latter) and then
+     * if one of them in non-zero call oldMethod on it.
+     *
+     * To call newMethod only a cast to FooInterface needs to be done.
+     *
+     * The Iface class does all this for you for up to three (for now) interface revisions. Just
+     * create an object like this:
+     * \code
+       Iface<FooInterface, FooInterface0> iface0(d);
+       if (iface0) {
+           iface0->oldMethod();
+       }
+       Iface<FooInterface> iface(d);
+       if (iface) {
+           iface->newMethod();
+       }
+     * \endcode
+     *
+     * This becomes a bit more convenient if you add macros like this:
+     * \code
+       #define IFACES1 FooInterface
+       #define IFACES0 IFACES1, FooInterface0
+     * \endcode
+     * which you can use like this:
+     * \code
+       Iface<IFACES0> iface0(d);
+       if (iface0) {
+           iface0->oldMethod();
+       }
+       Iface<IFACES1> iface(d);
+       if (iface) {
+           iface->newMethod();
+       }
+     * \endcode
+     * With the next revision you can then change the macros to
+     * \code
+       #define IFACES2 FooInterface
+       #define IFACES1 IFACES2, FooInterface1
+       #define IFACES0 IFACES1, FooInterface0
+     * \endcode
+     *
+     * \author Matthias Kretz <kretz@kde.org>
+     */
     template<class T0, class T1 = NoIface, class T2 = NoIface>
     class Iface
     {
[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic