music |
OSdata.com |
OSdata.com blog feed about computer science
|
- minimum wage for programmers May 7, 2015
- 256 files to control any computer July 25, 2014
- multiple inheritance in PHP July 2, 2014
- Studio Tool June 29, 2014
- OOP web site June 25, 2014
- What should Apple buy? May 28, 2014
- Timer/Clock May 26, 2014
- Geek Kit May 25, 2014
- 404 Redirects May 23, 2014
- Virtual Web Pages May 22, 2014
- California EDD and Windows XP May 15, 2014
- P = NP or not? May 12, 2014
- Average Pay May 5, 2014
- Engineering and Business February 16, 2014
- technology of the Sochi XXII Winter Olympics February 15, 2014
- Greg Gopman on the homeless December 12, 2013
- NSA uses Google cookies December 11, 2013
multiple inheritance in PHP
I have the need to introduce multiple inheritance into PHP and because the company policy is to offer everything we do as open source code (Apache License 2.0), I am presenting my design ideas before actually coding so that the development community can give feedback to make the finished source code better for everyone.
traits
I did take a look at the PHP traits feature and the fact is that it can do everything I need.
Unfortunately, you have to manually declare everything and you have to manually resolve all conflicts. That is acceptable for a simple task, but do you really need multiple inheritance for the simple tasks?
My goal is to build a robust system that is as automated as possible. To paraphrase, Steve Jobs, it should just work.
backwards compatibility
This software will be written so that it is compatible with PHPs existing built-in class capabilities. A programmer will be able to use both PHPs existing built-in class capabilities and our new multiple inheritance scheme in the same class. This will allow gradual introduction into existing systems.
base hashes
Under the proposed system, every class will have two base hashes (associative arrays in PHP), one for all attributes and one for all methods.
The programmer simply needs to remember to add two empty arrays at the beginning of their class definition.
class SomeClassName
{
public $attributehash;
public $methodhash;
your code goes here
}
The name of each attribute will be the key in the attribute hash and the value will be the contents of the attribute. Our code will search the entire multiple inheritance tree to discover every attribute at initialization time.
The name of each method will be the key in the method hash and the value will be a fully qualified method name. Our code will search the entire multiple inheritance tree to discover every method at initialization time.
We will use the PHP built-in functions get_class_vars and get_class_methods to make sure that we include all of the normally defined attributes and methods of each class. We will indicate in our attribute hash whether the attribute is stored in the hash or is located in the normal portion of the class declaration and act appropriately.
Note that these two arrays are declared public so that every class can find everything it needs. While this will allow a poor programmer to directly access anything, we are going to ask for the discipline of making all accesses through our control software.
singleton object
We will create a singleton object that manages the multiple inheritance. We will store the reference to this object in a global variable. I know, global variables are horrible, but this is the most simple way to make sure that the singleton object is available to every class anywhere in your code.
three working methods
We will have only three simple methods that are used in your working code (ignore initialization for the moment): get, set, and run.
The get method will be used to get (read) the contents of any attribute. This can be coded as a direct access or an access through a class method, at the programmers choice.
The set method will be used to set (put, write, modify) the contents of any attribute. This can be coded as a direct access or an access through a class method, at the programmers choice.
The run method will be used to access any method of a class.
Examples of each will follow:
get
Our get method will take an attribute name (as a string) and return the value (as whatever type is appropriate).
$result = $this->get('someattributename');
$result = $someobject->get('someattributename');
$result = $this->someattributename;
The last of those examples is supported by hooking our get method into the built-in __get.
Our get method will check to see if there is a programmer specified method for handling the fetch of the value of an attribute, and if, so will dispatch that method. Access control is left to the end programmer.
Next our get method will check access and throw an error on an unauthorized access attempt.
If we reach the third step, our get method will directly access and read the object attribute and return the value.
If we dont find either a matching method or attribute, then we will throw an error.
All attributes will be in the local object, either directly declared in the normal built-in PHP manner, inherited through the normal PHP inheritance model, or created at initialization and stored in our local attribute hash.
set
Our set method will take an attribute name (as a string) and some input value (as whatever type is appropriate).
$this->set('someattributename', value);
$someobject->set('someattributename',value);
$this->someattributename = value;
The last of those examples is supported by hooking our set method into the built-in __set.
Our set method will check to see if there is a programmer specified method for handling the storage of the value of an attribute, and if, so will dispatch that method. Access control is left to the end programmer.
Next our set method will check access and throw an error on an unauthorized access attempt.
If we reach the third step, our set method will directly access and write the designated value into the object attribute.
If we dont find either a matching method or attribute, then we will throw an error.
Future enhancements might include increment, decrement, and multiply-accumulate, in addition to simple modify in place. And we might also add multiprogramming/multithreading features such as locks, atomic read-write, and reductions (addition, subtraction, multiply, logical AND, logical OR, etc.).
All attributes will be in the local object, either directly declared in the normal built-in PHP manner, inherited through the normal PHP inheritance model, or created at initialization and stored in our local attribute hash.
run
Our run method will take a method name (as a string) and optional input value (as whatever type is appropriate) and return a result value (as whatever type is appropriate).
$this->set('somemethodname', value(s));
$someobject->set('somemethodname',value(s));
$this->somemethodname(value(s));
The last of those examples is supported by hooking our run method into the built-in __call and __callStatic.
We can use the built-in function func_get_args to allow for each method to get the correct number of arguments. For each step outlined below, realize that we will be packaging the incoming values in the manner expected by the
The run method will check to see if there is a programmer specified method, and if, so will dispatch that method. At the same time that we find the correct method, we will check for an unauthorized access attempt and throw an error if needed.
If we dont find a matching method, then we will throw an error.
Unlike the attributes, the appropriate method may or may not be coded directly in the local class. We will therefore store fully qualified method names so that we can dispatch inherited methods. This will work exactly the same regardless of whether the method is inherited through PHPs built-in inheritance model or our custom multiple inheritance model.
For future expansion, we can accept a series of string and value pairs to implement optional named inputs.
__construct
In addition to declaring our two special arrays, the programmer needs to also insert our initialization code at the very beginning of the __construct method.
private function __construct(input value(s));
{
include 'constructor.php'; /* feel free to substitute require */
registrations
early return check /* see notes below */
your initialization code
} /* END __construct */
Registration will be discussed below.
We bring in the construction code as an include or require so that it runs in the scope of the class __construct magic method.
We run our special code first so that all the inherited attributes and methods exist before the programmer starts any initialization.
building inheritance tree
At the very beginning of the program, the programmer will create our special singleton object and store the reference in a global variable.
Programmers will be able to make a call to a special function that lets our singleton object know the contents (attributes, methods, and built-in inheritance path) of classes.
This special function will simply create a temporary copy of an object of the specified class, run the initialization code, including the registration calls located there, record the information found in the singleton object, and finally delete the temporary object.
What about objects that make changes to the program state (or even worse, changes to the permanent stored information in files or databases)? We will run a special routine that can be called right after our code to return from the _construct function without running any of the rest of the normal initializations.
Next comes the special registration calls. The programmer uses these to provide our singleton object with instructions on multiple inheritance. This includes a specification of the order that the inheritance tree is to be searched.
And as a back-up, this code gets run each time an object is created. We will check to see if the class has already been registered. If the class has already been registered, we wont register it again, but otherwise we can register the class at the creation of the first instantiation of a class object. Registration at start-up is preferred, but this will help cover for a wide number of reasons why registration wasnt completed at program start-up.
Experienced programmers will notice that I havent yet specified the data structure that contains the inheritance tree nor the format for the registration calls. That is because I am still considering those implementation details. I want to emphasize clarity of the resulting code, so that everything is as self-documenting and easy to read as possible.
conclusion
I think I have covered all of the important details, including how this entire system can easily be integrated a little at a time into a large existing system.
At this point I am going to ask for feedback and suggestions. I do have a contact form below, but because of the ridiculous amount of spam I often miss real incoming messages. If you came to this page from a public forum, such as Google+, please respond there, as I will be much more likely to see your comments and suggestions.