Abusing Type Hinting in PHP

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.


9 Responses to Abusing Type Hinting in PHP

  1. 150 jose da silva 2008-06-20 04:46:47

    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!

  2. 151 harryr 2008-06-20 08:50:27

    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 :)

  3. 268 Catalin Z. Alexandru 2008-08-13 12:48:55

    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.

  4. 269 Catalin Z. Alexandru 2008-08-13 13:09:50

    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.

  5. 460 Catalin Z. Alexandru 2008-09-08 11:36:59

    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 :)

  6. 6309 Christian South 2010-08-09 14:04:09

    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

  7. 6310 Christian South 2010-08-09 14:05:55

    I can't edit my post above but I meant to say that the type hinting function is in PHP trunk

  8. 6400 Jonathan Hedrén 2010-08-30 17:54:01

    I would suggest using SPL Types (http://www.php.net/manual/en/book.spl-types.php) in favor of defining your own "primitive" classes.

  9. 6404 Harry 2010-08-31 09:38:22

    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.

Leave a Reply



About

Harry is a professional developer and sysadmin from London, UK.

He's an atheist, employed at PixelMags LLC, a socialist and has a pragmatic outlook on life, love and religion.

Bookmarks

I'm constantly finding interesting stuff, here are some of the things I've bookmarked recently:

HarryR on Faves.com