"Stig S. Bakken" wrote:
> Example set of classes using aggregate to customize at runtime:
> 
> DB_Connection          generic connection object
> DB_Connection_odbc     layer interfacing to PHP's odbc functions
> DB_Connection_oracle   ditto for Oracle
> DB_Connection_mysql    ditto for MySQL
> DB_SQL_oracle          SQL portability layer for Oracle
> DB_SQL_mysql           ditto for MySQL
> 
> If the user requests a connection to an Oracle database, 
> the connect function returns an instance of DB_Connection 
> that has aggregated DB_Connection_oracle and DB_SQL_oracle.
> 
> But if the user requests a connection to Oracle through ODBC, the
> connect function returns an instance of DB_Connection that has
> aggregated DB_Connection_odbc.  After connecting to the database,
> DB_Connection_odbc detects that it is used against Oracle and 
> aggregates DB_SQL_oracle.

You can do all this almost the same way you have shown using MI
and a factory object. You would premix your classes to get a
static (determined at compile time) mix, and have the factory
return the appropriately mixed class.

That's why I was using a generic RPC proxy and a Soaping mixin in
my example. In my example the actual classes being mixed are not
fixed, and are in fact not known until include_once() time
(runtime). Aggegration allows you to mix functionality into
existing classes dynamically, include_once() allows you to load
code dynamically. Thus, any attempt to solve this at compiletime
is doomed.

Generally speaking it is about class and type. A type describes
what an object can do, it's signature. The signature is a canonic
serialization of all its instance variable names and function
signatures. A class is where the object got these instance
variables and functions from.

In languages where class == type, functionality is either
inherited or locally defined. But there are languages where
functionality is not restricted to these sources but may be
provided in other ways. Aggregation is one way to get
functionality besides inheriance, and makes PHP a language where
class != type, if desired.

Traditionally, PHP always was class != type when it came to
instance variables. $this->$b was a valid construct for any $b
containing a valid variable name (and many invalid ones as well).
Traditionally PHP also was limited in how it could aquire
functions in objects, so it was class == type for functions of an
object. Aggregate fixed that by providing the missing API.

Stig's first attempt at aggregate() broke serialization and thus
sessions, because serialze() assumes that is enough to note the
class of an object in order to describe its type. That assumption
had always been false, but there was no API to break it. For
instance variables, serialize() always recorded the type, but for
methods it recorded the class as a reasonable shortcut.

In fact we could keep Stig's first version of aggregate(), if
serialize() recorded the type of an object for its methods, too.
It would have to write a log that describes how the object
aquired its functionality in order to recreate that upon
deserialization() (in PHPLIB terms, change

        $o = new Class;
        # aggregate($o, "anotherClass");

        $o->slot = 17;

so that the aggregate statement is recorded and generated in the
session data)

It is only because of the uglyness of this approach that Stig
revised his implementation of aggregate() so that it does not
break the (actually false) assumption of serialize() that class
== type for methods.

Kristian

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to