PHP has the ability to type hint function arguments to only accept that type or derivatives of that class or interface, this can lead to better interface design and much less runtime checking (as calling a type hinted function implicitly requires the parameter be of the correct type).
Can we go one step further though? Hacking on strict typing at the function level while allowing the benifits of weak typing within?
We do this by defining classes for all of the basic types: String, Number, Resource, Boolean as classes so they can be type hinted. For example:
class String {
public $value;
public function __construct( $value ) {
$this->value = $value;
}
}
And then repeat for the other basic types. What we end up is functions which can look like:
function myFunc( String $var1, Boolean $var2 ) {
$var1 = $var1->value;
$var2 = $var2->value;
// And so on
}
The memory overheads of this approach might not be justifyable, considering that classes take up much more memory than just the plain strings or booleans alone.
For strings as an example, this paves the way for String bass classes which provide a consistent interface for string operations with uniform names ala Java or C#.. or any other fully object orientated language (even Javascript). Looking at how naming fluctuates for string functions in PHP's core, this might be a distinct advantage.
See the differences:
- str_ireplace
- nl2br
- htmlspecialchars
- chunk_split
- quoted_printable_decode
- stripcslashes
- strip_tags
And so on...
Advantages
Using strict typing would allow for better error handling (the function cannot be called unless you give it the correct variable type) rather than failing horribly in the middle of a function because a resource was given instead of a string or number.
Disadvantages
You have to wrap your values with these special classes before you can call the function - this requires code modification and will not work with existing code.
$var1 = new String("Hello World");
$var2 = new Boolean(FALSE);
myFunc($var1, $var2);
Operator overloads will also hinder it's usefulness as the only type casting operator which can be used is `__toString`, so the following code will not work (which obviously is a major hinderance).
$var1 = new Number(10); $var2 = new Number(3); $var3 = $var1 / $var2; // Error!
Alternatives
I can pretty much presume that this is not going to be the best solution and will probably introduce more problems than it solves. One possible alternative is to use input contracts via asserts (which should be done any) to ensure that data types are valid before any processing is done.
The previous function `myFunc` would translate into:
function myFunc( $var1, $var2 ) {
assert( is_string($var1) );
assert( is_bool($var2) );
// Function logic here
}
It's not as declarative as the method described above, but it leads to better checks & hopefully better code quality in the long run.
Nice article,
Just a small typo on a function declaration
"function myFunc( String $var1, Boolean, $var2 )" you shoudl remove the "," after boolean.
The right way:
function myFunc( String $var1, Boolean $var2 )
Thanks for the great article!
That's very much my fault for not doing the code samples up in Eclipse/PDT before hand. Thanks for pointing it out, it's always appreciated :)
Oh God,
First of all I'd like to thank you, because your idea of wrapping basic data types into PHP classes just for the sake of Type Hinting and proper scalability inspired me.
Secondly. I'm working on a PHP Framework that's just as you say, "strong typed", having classes for ArrayContainer, String, Integer or Float and also for mixed values as StringOrInteger, StringOrBoolean and many more. I'd like to keep continuing this framework in an open-source license and invite you to join in the development of this framework. (which now has about 10.000 to 15.000 lines, depending if we includes modules or not) ...
If you can contact me by mail, I'll be glad to give you more details, and get the legal requirements to make the project open, and let you and me be the first developers of the first "strongly-typed" framework.
Looking forward to having innovative developers on-board.
Oh, and by the way. I've done testing using strong-typed classes against normal php data types. It seems that if you do something like:
for ($i = 0; $i 10000; ++$i) {
$str = new String ('something');
echo $str;
}
besides doing it the old way, the String class would be 24x slower. BUT, there is always a "BUT" ... in a big PHP framework, where you need to do "method-entry-contracts" for every method, the advantages of strong-typed classes for basic data types are beginning to get clearer. Why?! Because you would have something like this:
class A {
public function aMethod ($a, $b) {
if ($this->checkMe ($a)
do_something ();
}
}
class B extends A {
public function bMethod ($a, $b) {
if ($this->checkMe ($a)
do_something_with_them ();
do_another_thing_that_subtlety_changes_their_type ();
$this->aMethod () # again, useless checking in aMethod, just to be sure, useless function calls, when we could have defined aMethod (String $a, Integer $b) for example and got rid of USELESS CHECKS ...
}
}
Thus, if we have a method that has 5 parameters, we need to check every parameter. Ok. Sounds fair. But what if that method is used in a loop of 10.000 iterations. You guessed it: 50.000 function calls to $this->checkMe. Even a loop of 1.000 iterations (closer to reality) would mean 5.000 function calls.
Let's go a little further. How would strong-typed classes for basic PHP data types compare to that?! Well, a framework based on that wouldn't care about such things because of type-hinting. Thus, 1.000 iterations, on a method that KNOWS it must receive proper variables, would make the "method-entry-contract" useless, thus making the function execute faster about ... 5 function calls.
Getting a grip on things? I'm glad. :) Thanks "Code Bus", and you harry for the idea and I hope we're going to talk later.
Came back to say that it's possible. I finalized v2 of our framework, and works exclusivelly on "class datatypes". No significant performance loss, LOTS/TONS of stability fixes, more readable code thanks to the fact that we eliminated method-entry contracts. :)
You had the idea, I had the will. Thanks :)
I know this article is old I just wanted to add a note for anyone that finds it. PHP now has type casting for most if not all types so the above examples don't request a class. You can just do:
function myFunc(string $string, boolean $bool)
Nice article
I can't edit my post above but I meant to say that the type hinting function is in PHP trunk
I would suggest using SPL Types (http://www.php.net/manual/en/book.spl-types.php) in favor of defining your own "primitive" classes.
I'm well aware of SPL, the whole post is in-jest and poking at what I perceive as weaknesses in the language design of PHP and not to be taken seriously.