在类型提示时使用 JAVA 中的包装类 [重复]

Posted

技术标签:

【中文标题】在类型提示时使用 JAVA 中的包装类 [重复]【英文标题】:Use wrapper classes like in JAVA, when type hinting [duplicate] 【发布时间】:2015-01-14 08:00:19 【问题描述】:

php-s 类型提示中,我不能使用标量类型,如整数或字符串。所以这是无效的:

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

是否可以像在 JAVA 中那样使用包装类?整数、字符串、布尔值等...

我想这样使用它:

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


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

我知道,默认情况下,php 中没有包装类。但是怎么可能,写一个呢?

【问题讨论】:

您可以作为示例在测试函数中使用 is_integer 或 is_numeric 或 is_string 等... 是的,有可能,在手册的用户贡献部分中有解决方案:php.net/manual/en/language.oop5.typehinting.php 但我怀疑这是一个好主意。这会让其他开发人员感到困惑,并且可能会很慢。如果您想要一种静态类型的语言,请使用一种(如 java 或 facebooks Hack) 【参考方案1】:

从 PHP 5 开始,PHP 允许 type hinting 使用类(强制函数/方法的参数成为类的实例)。

因此,您可以创建一个int 类,该类在构造函数中采用 PHP 整数(如果您允许包含整数的字符串,则解析整数,如下例所示),并在函数的参数中期望它。

int

<?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;
   


演示

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

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

结果

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

但你应该小心副作用。

如果您在表达式中使用int 实例(例如$test + 1),则其计算结果将是true,而不是我们的例子中的42。您应该使用"$test" + 1 表达式来获取43,因为__toString 仅在尝试将您的对象转换为字符串时被调用。

注意:您不需要包装 array 类型,因为您可以在函数/方法的参数上进行原生类型提示。

float

<?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;
   


string

<?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;
   


bool

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;
   


object

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`
   


【讨论】:

我必须用 new 关键字创建每个 int 吗?是否有可能以某种方式实现自动装箱/拆箱? 不,PHP 不支持 :( 不,这不可能...使用这种类,就像在 C 中一样,您应该在使用它们之前声明您的变量(例如,$var = new int(42);` ),这在 php 中不太自然 :-)。【参考方案2】:

没有原始值的包装类,没有。我想你可以手动检查类型:

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

不过,这不是真正的类型提示。

最好的方法可能是很好地记录您的代码并希望它被正确使用。

/**
 * @param int $num
 */
function myFunc($num) 
    // ...

【讨论】:

以上是关于在类型提示时使用 JAVA 中的包装类 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

Java基础知识(JAVA基本数据类型包装类)

Java基本数据类型与包装类型(转)

Java api 入门教程 之 JAVA的包装类

Java包装类详解

JavaSE包装类基本类型和字符串之间的转换==和equals的区别

为啥java的一些概念需要使用包装类而不是原始数据类型[重复]