You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Alex Kiesel edited this page Jun 7, 2012
·
7 revisions
Class loading
In the XP framework, all classes are organized into packages. A package
contains subpackages and classes. Any such item has a fully qualified
name consisting of the containing package's name and the name itself.
Naming
Qualified names may consist of any letter from [a..zA..Z], the underscore (_) and may contain numbers [0..9] (except at the beginning!). The name parts are separated by dots (".").
Examples
lang.XPClass - the class "XPClass" in the package
"lang" - represented by lang/XPClass.class.php
util.collections - the package "collections", a
a subpackage of the "util" package (util/collections).
Additional classes to the framework should be named according to the "reverse domain" principle also used in Java. The classes that form the Dialog application (a photoblog software) reside in de.thekid.
uses()
Static dependencies can be written using the uses() statement as follows:
Usually we want to actually do something with this class, so we'd create an lang.XPClass instance from it. So instead of the above, the common practice is to write:
Used primarily as "throw-away" objects or as a substitution for closures, the XP framework allows for anonymous classes to be created via newinstance():
<?php$cleanup= newinstance('lang.Runnable', array($this->base), '{ private $base; public function __construct(Folder $base) { $this->base= $base; } public function run() { Console::writeLine("Cleaning temporary files in ", $this->base); } }');
?>
Classes created by newinstance() will be named using the base class' local name (here: Runnable) and a unique identifier. Typically, this class will be named Runnable·1.
Proxy classes
To create anonymous instances from interfaces and pass control to a separate instances, the lang.reflect.Proxy class can be used:
<?php$handler= newinstance('lang.reflect.InvocationHandler', array(), '{ public function invoke($method, $args) { Console::writeLine("Invoke ", $method, "(", $args, ")"); } }');
$proxy= Proxy::newProxyInstance(
ClassLoader::getDefault(),
array(XPClass::forName('lang.Runnable')),
$handler
);
// Will print "Invoke run([])" on the console output$proxy->run();
?>
This method is used in the remote package for example, where the invocation handler serializes the invocation, sends it to server, reads the answer, unserializes it and return the obtained value.
Classes created by the Proxy class will be named using the prefix "Proxy·" and a unique identifier.
ClassLoader
The lang.ClassLoader apidocs: lang.ClassLoader] class functions as an entry point for all class loading operations. It maintains a list of delegates which it asks to load classes, packages and resources. For each distinct element in PHP's include_path setting, a class loader delegate will be created.
A note on distinction: In case the current working directory is /home/thekid/classes, there will only be two delegates (#2 and #3 from above). Uniqueness is determined by comparing the elements after having applied realpath() on them.
To programmatically add delegates, use the following:
The class loading mechanism will search for classes by asking each of its delegates if they provide classes by the given fully qualified names. The first delegate classloader to return true will be asked to load the given class.
Inner workings
Once a class is found and has not been previously loaded, the following is typically performed:
Transform the fully qualified name to the storage name.
On Windows systems using the released XAR files, lang.XPClass
becomes something like xar://c:/Opt/XP/5.6.6/lib/xp-rt-5.6.6.xar?lang/XPClass.class.php.
Using PHP's stream wrapper functionality, the storage name is passed to the include() statement.
The class bytes are loaded and evaluated.
The class is registered. Its fully qualified name and the classloader are stored for later reverse lookup.