PHP类的隐式类型转换?

时间:2022-02-27 17:04:20

Is there a way to tell the php complier that I want a specific implicit conversion from one type to another?

有没有办法告诉php编译器我想从一种类型到另一种类型的特定隐式转换?

A simple example:

一个简单的例子:

class Integer
{
  public $val;
}

function ExampleFunc(Interger $i){...}

ExamFunc(333); // 333 -> Integer object with $val == 333.

[edit]... someone asked for an example. Here's an example from c#. This is a boolean type that changes value after it has been accessed once.

[编辑] ...有人问了一个例子。这是c#的一个例子。这是一个布尔类型,在访问一次后更改值。

    /// <summary>
    /// A Heisenberg style boolean that changes after it has been read. Defaults to false.
    /// </summary>
    public class hbool
    {
        private bool value;
        private bool changed = false;

        public hbool()
        {
            value = false;
        }

        public hbool(bool value)
        {
            this.value = value;
        }

        public static implicit operator bool(hbool item)
        {
            return item.Value;
        }

        public static implicit operator hbool(bool item)
        {
            return new hbool(item);
        }

        public bool Value
        {
            get
            {
                if (!changed)
                {
                    value = !value;
                    changed = true;
                    return !value;
                }
                return value;
            }
        }

        public void TouchValue()
        {
            bool value1 = Value;
        }

        public static hbool False
        {
            get { return new hbool(); }
        }

        public static hbool True
        {
            get { return new hbool(true); }
        }
    }

        [Test]
        public void hboolShouldChangeAfterRead()
        {
            hbool b = false;
            Assert.IsFalse(b);
            Assert.IsTrue(b);
            Assert.IsTrue(b);
            hbool b1 = false;
            Assert.IsFalse(b1);
            Assert.IsTrue(b1);
            Assert.IsTrue(b1);
            hbool b2 = true;
            Assert.IsTrue(b2);
            Assert.IsFalse(b2);
            Assert.IsFalse(b2);
            bool b3 = new hbool();
            Assert.IsFalse(b3);
            Assert.IsFalse(b3);
            Assert.IsFalse(b3);
        }

7 个解决方案

#1


Long answer:

I think it is very difficult (read impossible) for PHP to do an implicit conversion in this case.

我认为PHP在这种情况下进行隐式转换非常困难(读不可能)。

Remember: the fact that you call your class Integer is a hint to the human reader of the code, PHP does not understand that it actually is used to hold an integer. Also, the fact that it has an attribute called $val is a hint to a human reader that it should probably contain the value of your integer. Again PHP does not understand your code, it only executes it.

记住:你调用你的类Integer的事实是对代码的人类读者的提示,PHP不明白它实际上用于保存整数。此外,它有一个名为$ val的属性的事实是一个人类读者提示它应该包含整数的值。 PHP不会理解您的代码,它只会执行它。

At some point in your code you should do an explicit conversion. It might be possible that PHP has some nice syntactig sugar for that, but a first attempt would be something like:

在代码中的某个时刻,您应该进行显式转换。有可能PHP有一些很好的syntactig糖,但第一次尝试将是这样的:

class Integer
{
  public $val;

  function __construct($val) { $this->val = $val; }
}

function ExampleFunc($i){
    if (is_numeric($i)) { $iObj = new Integer($i); }
    ...
}

ExamFunc(333); // 333 -> Integer object with $val === 333.

This is not as cool as you would like it, but again, it is possible that PHP has some syntactic sugar that will hide the explicit conversion more or less.

这并不像你想要的那么酷,但同样,PHP可能会有一些语法糖,它会或多或少地隐藏显式转换。

Short version:

In one way or another, you will need an explicit conversion

以这种或那种方式,您将需要显式转换

#2


PHP5 has type hinting, with limitations: http://ca2.php.net/manual/en/language.oop5.typehinting.php

PHP5有类型提示,但有局限性:http://ca2.php.net/manual/en/language.oop5.typehinting.php

Specified types must be objects or array, so built in types such as string and int are not allowed.

指定的类型必须是对象或数组,因此不允许使用内置类型(如string和int)。

This is not a conversion, but will throw an error if an object of the specified type is not passed to the method or function, as in your example.

这不是转换,但如果未将指定类型的对象传递给方法或函数,则会抛出错误,如示例所示。

#3


Actually this possible with the SPL_Type extension. It defines classes for primitive types whose objects operate interchangeably with the PHP's primitive types (booleans, enums, ints, floats and strings).

实际上这可能与SPL_Type扩展。它定义了基本类型的类,其对象可以与PHP的基本类型(布尔值,枚举,整数,浮点数和字符串)互换。

You first example would work by simply inheriting from SplIt as follows:

您可以通过简单地继承SplIt来实现第一个示例,如下所示:

class Integer extends extends \SplInt{}

function ExampleFunc(Interger $i){...}

ExamFunc(333); // 333 -> Integer object with $val == 333.

The problem is that the code of the SplTypes extension hasn't been maintained since 2012, and by the moment of this post, it hasn't ported to PHP 7, nor there is a plan for such.

问题是SplTypes扩展的代码自2012年以来一直没有得到维护,到目前为止,它还没有移植到PHP 7,也没有这样的计划。

UPDATE I have found the following unnofficial port of SPL Types to PHP 7. Use at your own risk: https://github.com/esminis/php_pecl_spl_types

更新我发现以下非正式的SPL类型端口到PHP 7.使用风险由您自己承担:https://github.com/esminis/php_pecl_spl_types

Basic installation instructions:

基本安装说明:

  1. Clone code: https://github.com/esminis/php_pecl_spl_types.git
  2. 克隆代码:https://github.com/esminis/php_pecl_spl_types.git

  3. Generate the configure file. Inside the code directory type:phpize.
  4. 生成配置文件。在代码目录里面输入:phpize。

  5. Generate make file: ./configure
  6. 生成make文件:./ configure

  7. Compile code and install: make && make install
  8. 编译代码并安装:make && make install

  9. Add the module to your PHP configuraiton. At Ubuntu, type echo "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini
  10. 将模块添加到PHP配置中。在Ubuntu中,键入echo“extension = spl_types.so”> /etc/php7/conf.d/spl_types.ini

  11. Restart your PHP-FPM (if using it): service php7.0-fpm restart
  12. 重启你的PHP-FPM(如果使用它):service php7.0-fpm restart

#4


No, PHP is not a strongly typed language.

不,PHP不是强类型语言。

#5


Are you asking how to type cast? You can do:

你在问如何输入演员吗?你可以做:

$ php -r 'var_dump("333");'
string(3) "333"
$ php -r 'var_dump((int)"333");'
int(333)

Otherwise PHP is weakly typed, so in general you don't need to do it. It's implied by the language. Eg. if a function takes a numeric argument, then that number can be string, integer or float all the same; The value is converted if needed. That's why you can for example echo 33 without an error.

否则PHP是弱类型的,所以通常你不需要这样做。它隐含在语言中。例如。如果函数采用数字参数,则该数字可以是字符串,整数或浮点数;如果需要,将转换该值。这就是为什么你可以回答33没有错误。

#6


PHP is not strongly typed.

PHP没有强类型。

You want something like, whenever you pass an hbool instance into a function that expects a bool it would convert automatically using your implicit conversor.

每当你将一个hbool实例传递给一个期望bool它会使用你的隐式转换自动转换的函数时,你想要类似的东西。

What happens is that no function "expects" a bool, it's all dynamically typed. You can force an explicit conversion by calling (int)$something but if that's the case you can then pass $something->to_otherthing() instead for non-automatic conversions.

会发生什么是没有函数“期望”一个bool,它都是动态类型的。您可以通过调用(int)$ something来强制显式转换,但如果是这种情况,则可以将$ something-> to_otherthing()传递给非自动转换。

PS: I'm sure im not being clear here. I will try to edit this answer after I eat something :)

PS:我确定我不清楚这里。吃完之后我会尝试编辑这个答案:)

#7


This question is very old, but I would like to give a solution. This behaviour is called boxing which can be done in PHP, but the inverse of this, unboxing see:

这个问题很老了,但我想给出一个解决方案。这种行为称为拳击,可以在PHP中完成,但与此相反,取消装箱请参阅:

function a(int $a){...}

a(new Integer(1));

is not possible currently. If you want a framework which offers you this and even more, look at the BlazeFramework which has such wrapper classes.

目前是不可能的。如果你想要一个为你提供这个甚至更多的框架,请查看具有这种包装类的BlazeFramework。

Operation overloading does not work either in php. The implementation is maybe a bit too much to write, but I give you a hint! PHP calls the callback set with set_error_handler() with the error level E_RECOVERABLE_ERROR and debug_backtrace() delivers information about the function/method call.

操作重载在php中都不起作用。实现可能有点太多了,但我给你一个提示! PHP使用set_error_handler()调用回调集,错误级别为E_RECOVERABLE_ERROR,debug_backtrace()提供有关函数/方法调用的信息。

If you don't get that, look at the implementation of the method blaze\lang\System#systemErrorHandler(), but possibly it is better to just use the framework if you want more of such features.

如果你没有这样做,请查看方法blaze \ lang \ System#systemErrorHandler()的实现,但如果你想要更多这样的功能,最好只使用框架。

#1


Long answer:

I think it is very difficult (read impossible) for PHP to do an implicit conversion in this case.

我认为PHP在这种情况下进行隐式转换非常困难(读不可能)。

Remember: the fact that you call your class Integer is a hint to the human reader of the code, PHP does not understand that it actually is used to hold an integer. Also, the fact that it has an attribute called $val is a hint to a human reader that it should probably contain the value of your integer. Again PHP does not understand your code, it only executes it.

记住:你调用你的类Integer的事实是对代码的人类读者的提示,PHP不明白它实际上用于保存整数。此外,它有一个名为$ val的属性的事实是一个人类读者提示它应该包含整数的值。 PHP不会理解您的代码,它只会执行它。

At some point in your code you should do an explicit conversion. It might be possible that PHP has some nice syntactig sugar for that, but a first attempt would be something like:

在代码中的某个时刻,您应该进行显式转换。有可能PHP有一些很好的syntactig糖,但第一次尝试将是这样的:

class Integer
{
  public $val;

  function __construct($val) { $this->val = $val; }
}

function ExampleFunc($i){
    if (is_numeric($i)) { $iObj = new Integer($i); }
    ...
}

ExamFunc(333); // 333 -> Integer object with $val === 333.

This is not as cool as you would like it, but again, it is possible that PHP has some syntactic sugar that will hide the explicit conversion more or less.

这并不像你想要的那么酷,但同样,PHP可能会有一些语法糖,它会或多或少地隐藏显式转换。

Short version:

In one way or another, you will need an explicit conversion

以这种或那种方式,您将需要显式转换

#2


PHP5 has type hinting, with limitations: http://ca2.php.net/manual/en/language.oop5.typehinting.php

PHP5有类型提示,但有局限性:http://ca2.php.net/manual/en/language.oop5.typehinting.php

Specified types must be objects or array, so built in types such as string and int are not allowed.

指定的类型必须是对象或数组,因此不允许使用内置类型(如string和int)。

This is not a conversion, but will throw an error if an object of the specified type is not passed to the method or function, as in your example.

这不是转换,但如果未将指定类型的对象传递给方法或函数,则会抛出错误,如示例所示。

#3


Actually this possible with the SPL_Type extension. It defines classes for primitive types whose objects operate interchangeably with the PHP's primitive types (booleans, enums, ints, floats and strings).

实际上这可能与SPL_Type扩展。它定义了基本类型的类,其对象可以与PHP的基本类型(布尔值,枚举,整数,浮点数和字符串)互换。

You first example would work by simply inheriting from SplIt as follows:

您可以通过简单地继承SplIt来实现第一个示例,如下所示:

class Integer extends extends \SplInt{}

function ExampleFunc(Interger $i){...}

ExamFunc(333); // 333 -> Integer object with $val == 333.

The problem is that the code of the SplTypes extension hasn't been maintained since 2012, and by the moment of this post, it hasn't ported to PHP 7, nor there is a plan for such.

问题是SplTypes扩展的代码自2012年以来一直没有得到维护,到目前为止,它还没有移植到PHP 7,也没有这样的计划。

UPDATE I have found the following unnofficial port of SPL Types to PHP 7. Use at your own risk: https://github.com/esminis/php_pecl_spl_types

更新我发现以下非正式的SPL类型端口到PHP 7.使用风险由您自己承担:https://github.com/esminis/php_pecl_spl_types

Basic installation instructions:

基本安装说明:

  1. Clone code: https://github.com/esminis/php_pecl_spl_types.git
  2. 克隆代码:https://github.com/esminis/php_pecl_spl_types.git

  3. Generate the configure file. Inside the code directory type:phpize.
  4. 生成配置文件。在代码目录里面输入:phpize。

  5. Generate make file: ./configure
  6. 生成make文件:./ configure

  7. Compile code and install: make && make install
  8. 编译代码并安装:make && make install

  9. Add the module to your PHP configuraiton. At Ubuntu, type echo "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini
  10. 将模块添加到PHP配置中。在Ubuntu中,键入echo“extension = spl_types.so”> /etc/php7/conf.d/spl_types.ini

  11. Restart your PHP-FPM (if using it): service php7.0-fpm restart
  12. 重启你的PHP-FPM(如果使用它):service php7.0-fpm restart

#4


No, PHP is not a strongly typed language.

不,PHP不是强类型语言。

#5


Are you asking how to type cast? You can do:

你在问如何输入演员吗?你可以做:

$ php -r 'var_dump("333");'
string(3) "333"
$ php -r 'var_dump((int)"333");'
int(333)

Otherwise PHP is weakly typed, so in general you don't need to do it. It's implied by the language. Eg. if a function takes a numeric argument, then that number can be string, integer or float all the same; The value is converted if needed. That's why you can for example echo 33 without an error.

否则PHP是弱类型的,所以通常你不需要这样做。它隐含在语言中。例如。如果函数采用数字参数,则该数字可以是字符串,整数或浮点数;如果需要,将转换该值。这就是为什么你可以回答33没有错误。

#6


PHP is not strongly typed.

PHP没有强类型。

You want something like, whenever you pass an hbool instance into a function that expects a bool it would convert automatically using your implicit conversor.

每当你将一个hbool实例传递给一个期望bool它会使用你的隐式转换自动转换的函数时,你想要类似的东西。

What happens is that no function "expects" a bool, it's all dynamically typed. You can force an explicit conversion by calling (int)$something but if that's the case you can then pass $something->to_otherthing() instead for non-automatic conversions.

会发生什么是没有函数“期望”一个bool,它都是动态类型的。您可以通过调用(int)$ something来强制显式转换,但如果是这种情况,则可以将$ something-> to_otherthing()传递给非自动转换。

PS: I'm sure im not being clear here. I will try to edit this answer after I eat something :)

PS:我确定我不清楚这里。吃完之后我会尝试编辑这个答案:)

#7


This question is very old, but I would like to give a solution. This behaviour is called boxing which can be done in PHP, but the inverse of this, unboxing see:

这个问题很老了,但我想给出一个解决方案。这种行为称为拳击,可以在PHP中完成,但与此相反,取消装箱请参阅:

function a(int $a){...}

a(new Integer(1));

is not possible currently. If you want a framework which offers you this and even more, look at the BlazeFramework which has such wrapper classes.

目前是不可能的。如果你想要一个为你提供这个甚至更多的框架,请查看具有这种包装类的BlazeFramework。

Operation overloading does not work either in php. The implementation is maybe a bit too much to write, but I give you a hint! PHP calls the callback set with set_error_handler() with the error level E_RECOVERABLE_ERROR and debug_backtrace() delivers information about the function/method call.

操作重载在php中都不起作用。实现可能有点太多了,但我给你一个提示! PHP使用set_error_handler()调用回调集,错误级别为E_RECOVERABLE_ERROR,debug_backtrace()提供有关函数/方法调用的信息。

If you don't get that, look at the implementation of the method blaze\lang\System#systemErrorHandler(), but possibly it is better to just use the framework if you want more of such features.

如果你没有这样做,请查看方法blaze \ lang \ System#systemErrorHandler()的实现,但如果你想要更多这样的功能,最好只使用框架。