用户定义对象的类型转换

2021-12-31 00:00:00 casting php

就像我们对 __ToString 所做的那样,有没有一种方法可以定义一个用于转换的方法?

$obj = (MyClass) $another_class_obj;

解决方案

php 中不需要 type cast.

<小时>

由于这个话题似乎引起了一些混乱,我想我会详细说明一下.

在 Java 等语言中,有两种东西可以携带类型.编译器有一个关于类型的概念,而运行时有另一个关于类型的概念.编译器类型与变量相关联,而运行时引擎跟踪值的类型(分配给变量).变量类型在编译时已知,而值类型仅在运行时已知.

如果一段输入代码违反了编译器的类型系统,编译器将停止编译.换句话说,编译一段违反静态类型系统的代码是不可能的.这会捕获特定类别的错误.例如,采用以下(简化的)Java 代码:

class Alpha {}类 Beta 扩展了 Alpha {公共无效 sayHello() {System.out.println("你好");}}

如果我们现在这样做:

Alpha a = new Beta();

我们会没事的,因为 BetaAlpha 的子类,因此是 a 类型变量的有效值>Alpha.但是,如果我们继续这样做:

a.sayHello();

编译器会报错,因为方法 sayHello 不是 Alpha 的有效方法 - 不管我们知道 a实际上是一个Beta.

输入类型转换:

((Beta) a).sayHello();

这里我们告诉编译器变量 a 应该 - 在这种情况下 - 被视为 Beta.这称为类型转换.这个漏洞非常有用,因为它允许语言中的多态性,但显然它也是各种违反类型系统的后门.为了保持某种类型安全,因此存在一些限制;您只能转换为相关的类型.例如.在层次结构中向上或向下.换句话说,您将无法转换为完全不相关的类 Charlie.

需要注意的是,所有这些都发生在编译器中——也就是说,它甚至在代码运行之前就发生了.Java 仍然会出现运行时类型错误.例如,如果您这样做:

class Alpha {}类 Beta 扩展了 Alpha {公共无效 sayHello() {System.out.println("你好");}}class Charlie 扩展了 Alpha {}阿尔法 a = 新查理();((Beta) a).sayHello();

以上代码对编译器有效,但在运行时,您会得到一个异常,因为从 BetaCharlie 的转换是不兼容的.>

与此同时,回到 PHP 农场.

以下内容对 PHP 编译器有效 - 它很乐意将其转换为可执行字节代码,但您会收到运行时错误:

class Alpha {}类 Beta 扩展了 Alpha {函数 sayHello() {打印你好";}}$a = 新阿尔法();$a->sayHello();

这是因为 PHP 变量没有类型.编译器不知道哪些运行时类型对变量有效,因此它不会尝试强制执行它.您也不像在 Java 中那样显式指定类型.有类型提示,是的,但这些只是运行时合同.以下内容仍然有效:

//重用上面的类函数 tellToSayHello(Alpha $a) {$a->sayHello();}tellToSayHello(new Beta());

即使 PHP 变量没有类型,值仍然有.PHP 的一个特别有趣的方面是可以更改值的类型.例如:

//变量 $foo 保存一个字符串类型的值$foo = "42";echo gettype($foo);//产生字符串"//这里我们改变了字符串的类型 ->整数settype($foo, "整数");echo gettype($foo);//产生整数"

此功能有时会与类型转换混淆,但这是用词不当.类型仍然是值的一个属性,类型改变发生在运行时——而不是在编译时.

更改类型的能力在 PHP 中也相当有限.只能在简单类型之间更改类型 - 而不是对象.因此,不可能将类型从一个类更改为另一个类.您可以创建一个新对象并复制状态,但无法更改类型.PHP 在这方面有点局外人;其他类似的语言将类视为一个比 PHP 更动态的概念.

PHP 的另一个类似功能是您可以将值克隆为新类型,如下所示:

//变量 $foo 保存一个字符串类型的值$foo = "42";echo gettype($foo);//产生字符串"//这里我们改变了字符串的类型 ->整数$bar = (整数) $foo;echo gettype($bar);//产生整数"

从语法上看,这看起来很像用静态类型语言编写的类型转换.因此它也经常与类型转换混淆,即使它仍然是运行时类型转换.

总结:类型转换是一种改变变量类型(不是值)的操作.由于PHP中的变量是无类型的,所以这不仅是不可能做到的,而且首先问是无稽之谈.

Just like we do with __ToString, is there a way to define a method for casting?

$obj = (MyClass) $another_class_obj;

解决方案

There is no need to type cast in php.


Edit: Since this topic seems to cause some confusion, I thought I'd elaborate a little.

In languages such as Java, there are two things that may carry type. The compiler has a notion about type, and the run time has another idea about types. The compilers types are tied to variables, whereas the run time engine tracks the type of values (Which are assigned to variables). The variable types are known at compile time, whereas the value types are only known at run time.

If a piece of input code violates the compilers type system, the compiler will barf and halt compilation. In other words, it's impossible to compile a piece of code that violates the static type system. This catches a certain class of errors. For example, take the following piece of (simplified) Java code:

class Alpha {}

class Beta extends Alpha {
  public void sayHello() {
    System.out.println("Hello");
  }
}

If we now did this:

Alpha a = new Beta();

we would be fine, since Beta is a subclass of Alpha, and therefore a valid value for the variable a of type Alpha. However, if we proceed to do:

a.sayHello();

The compiler would give an error, since the method sayHello isn't a valid method for Alpha - Regardless that we know that a is actually a Beta.

Enter type casting:

((Beta) a).sayHello();

Here we tell the compiler that the variable a should - in this case - be treated as a Beta. This is known as type casting. This loophole is very useful, because it allows polymorphism in the language, but obviously it is also a back door for all sorts of violations of the type system. In order to maintain some type safety, there are therefore some restrictions; You can only cast to types that are related. Eg. up or down a hierarchy. In other words, you wouldn't be able to cast to a completely unrelated class Charlie.

It's important to note that all this happens in the compiler - That is, it happens before the code even runs. Java can still get in to run time type errors. For example, if you did this:

class Alpha {}

class Beta extends Alpha {
  public void sayHello() {
    System.out.println("Hello");
  }
}

class Charlie extends Alpha {}

Alpha a = new Charlie();
((Beta) a).sayHello();

The above code is valid for the compiler, but at run time, you'll get an exception, since the cast from Beta to Charlie is incompatible.

Meanwhile, back at the PHP-farm.

The following is valid to the PHP-compiler - It'll happily turn this into executable byte code, but you'll get a run time error:

class Alpha {}

class Beta extends Alpha {
  function sayHello() {
    print "Hello";
  }
}
$a = new Alpha();
$a->sayHello();

This is because PHP variables don't have type. The compiler has no idea about what run time types are valid for a variable, so it doesn't try to enforce it. You don't specify the type explicitly as in Java either. There are type hints, yes, but these are simply run time contracts. The following is still valid:

// reuse the classes from above
function tellToSayHello(Alpha $a) {
  $a->sayHello();
}
tellToSayHello(new Beta());

Even though PHP variables don't have types, the values still do. A particular interesting aspect of PHP, is that it is possible to change the type of a value. For example:

// The variable $foo holds a value with the type of string
$foo = "42";
echo gettype($foo); // Yields "string"
// Here we change the type from string -> integer
settype($foo, "integer");
echo gettype($foo); // Yields "integer"

This feature some times confused with type casting, but that is a misnomer. The type is still a property of the value, and the type-change happens in runtime - not at compile time.

The ability to change type is also quite limited in PHP. It is only possible to change type between simple types - not objects. Thus, it isn't possible to change the type from one class to another. You can create a new object and copy the state, but changing the type isn't possible. PHP is a bit of an outsider in this respect; Other similar languages treat classes as a much more dynamic concept than PHP does.

Another similar feature of PHP is that you can clone a value as a new type, like this:

// The variable $foo holds a value with the type of string
$foo = "42";
echo gettype($foo); // Yields "string"
// Here we change the type from string -> integer
$bar = (integer) $foo;
echo gettype($bar); // Yields "integer"

Syntactically this looks a lot like how a typecast is written in statically typed languages. It's therefore also often confused with type casting, even though it is still a runtime type-conversion.

To summarise: Type casting is an operation that changes the type of a variable (not the value). Since variables are without type in PHP, it is not only impossible to do, but a nonsensical thing to ask in the first place.

相关文章