Use wrapper classes like in JAVA, when type hinting [duplicate]
Asked Answered
T

2

7

In php-s type hinting, I cannot use scalar types, like integer, or string. So this is invalid:

function myFunc(int $num) {
    //...
}

Is it possible to use wrapper classes, like in JAVA? Integer, String, Boolean, etc...

I would like to use it like this:

function myFunc(Integer $num) {
    //...
}

myFunc(5);     // ok
myFunc("foo"); // error

I know, there are no wrapper classes in php by default. But how is it possible, to write one?

Theron answered 17/11, 2014 at 11:54 Comment(2)
You can as example inside a test function use is_integer or is_numeric or is_string, etc...Cytogenetics
Yes its possible, there are solutions for this in user contributed section of the manual: php.net/manual/en/language.oop5.typehinting.php But i doubt it is a good idea. It will be confusing to other developers, and probably slow. If you want a statically typed language, use one (like java, or facebooks Hack)Shu
S
5

Since PHP 5, PHP allows type hinting using classes (forcing a function/method's parameter to be an instance of a classs).

So you can create an int class that takes a PHP integer in constructor (or parsing an integer if you allow a string containing an integer, such as in the example below), and expect it in a function's parameter.

The int class

<?php

class int
{

   protected $value;

   public function __construct($value)
   {
      if (!preg_match("/^(0|[-]?[1-9][0-9])*$/", "$value"))
      {
         throw new \Exception("{$value} is not a valid integer.");
      }
      $this->value = $value;
   }

   public function __toString()
   {
      return '' . $this->value;
   }

}

Demo

$test = new int(42);
myFunc($test);

function myFunc(int $a) {
  echo "The number is: $a\n";
}

Result

KolyMac:test ninsuo$ php types.php 
The number is: 42
KolyMac:test ninsuo$ 

But you should be careful about side effects.

Your int instance will evaluate to true if you're using it inside an expression (such as, $test + 1), instead of 42 in our case. You should use the "$test" + 1 expression to get 43, as the __toString is only called when trying to cast your object to a string.

Note: you don't need to wrap the array type, as you can natively type-hint it on function/method's parameters.

The float class

<?php

class float
{

   protected $value;

   public function __construct($value)
   {
      if (!preg_match("/^(0|[-]?[1-9][0-9]*[\.]?[0-9]*)$/", "$value"))
      {
         throw new \Exception("{$value} is not a valid floating number.");
      }
      $this->value = $value;
   }

   public function __toString()
   {
      return $this->value;
   }

}

The string class

<?php

class string
{

   protected $value;

   public function __construct($value)
   {
      if (is_array($value) || is_resource($value) || (is_object($value) && (!method_exists($value, '__toString'))))
      {
         throw new \Exception("{$value} is not a valid string or can't be converted to string.");
      }
      $this->value = $value;
   }

   public function __toString()
   {
      return $this->value;
   }

}

The bool class

class bool
{

   protected $value;

   public function __construct($value)
   {
      if (!strcasecmp('true', $value) && !strcasecmp('false', $value) 
          && !in_array($value, array(0, 1, false, true)))
      {
         throw new \Exception("{$value} is not a valid boolean.");
      }
      $this->value = $value;
   }

   public function __toString()
   {
      return $this->value;
   }

}

The object class

class object
{

   protected $value;

   public function __construct($value)
   {
      if (!is_object($value))
      {
         throw new \Exception("{$value} is not a valid object.");
      }
      $this->value = $value;
   }

   public function __toString()
   {
      return $this->value; // your object itself should implement __tostring`
   }

}
Sixtyfour answered 19/11, 2014 at 13:51 Comment(3)
I have to create every int with the new keyword? Isn't it possible, to implement autoboxing/unboxing somehow?Theron
No, PHP doesn't support that :(Fourwheeler
Nope, that's not possible... Using this kind of classes, this is like in C, you should declare your variables before using them (such as, $var = new int(42);`), that's not quite natural in php :-).Sixtyfour
L
1

There are no wrapper classes for primitive values, no. I guess you could manually check the type:

function myFunc($num) {
    if( !is_int($num) ) {
        throw new Exception('First parameter must be a number');
    }
    // ...
}

It wouldn't be true type hinting, though.

The best way would probably be documenting your code well and hoping it is used correctly.

/**
 * @param int $num
 */
function myFunc($num) {
    // ...
}
Lessee answered 17/11, 2014 at 12:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.