"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