用户定义对象的类型强制转换
就像我们对__ToString所做的那样,有没有办法定义铸造方法?
$obj = (MyClass) $another_class_obj;
就像我们对__ToString所做的那样,有没有办法定义铸造方法?
$obj = (MyClass) $another_class_obj;
没有必要在php中键入cast。
编辑:由于这个话题似乎引起了一些混乱,我想我会详细阐述一下。
在Java等语言中,有两个东西可能带有类型。编译器有一个关于类型的概念,而运行时有另一个关于类型的概念。编译器类型与变量相关联,而运行时引擎跟踪值的类型(分配给变量)。变量类型在编译时是已知的,而值类型仅在运行时是已知的。
如果一段输入代码违反了编译器类型系统,编译器将 barf 并暂停编译。换句话说,不可能编译一段违反静态类型系统的代码。这会捕获特定类别的错误。例如,采用以下(简化的)Java 代码:
class Alpha {}
class Beta extends Alpha {
public void sayHello() {
System.out.println("Hello");
}
}
如果我们现在这样做:
Alpha a = new Beta();
我们就可以了,因为它是 的子类,因此是 类型变量的有效值。但是,如果我们继续这样做:Beta
Alpha
a
Alpha
a.sayHello();
编译器会给出一个错误,因为该方法不是 - 无论我们知道它实际上是一个.sayHello
Alpha
a
Beta
输入类型转换:
((Beta) a).sayHello();
在这里,我们告诉编译器,在这种情况下,变量应该被视为 .这称为类型转换。这个漏洞非常有用,因为它允许在语言中多态性,但显然它也是各种违反类型系统的后门。为了保持某种类型安全,因此有一些限制;只能强制转换为相关的类型。例如。向上或向下层次结构。换句话说,您将无法强制转换为完全不相关的类 。a
Beta
Charlie
重要的是要注意,所有这些都发生在编译器中 - 也就是说,它发生在代码运行之前。Java 仍然可以进入运行时类型错误。例如,如果您执行以下操作:
class Alpha {}
class Beta extends Alpha {
public void sayHello() {
System.out.println("Hello");
}
}
class Charlie extends Alpha {}
Alpha a = new Charlie();
((Beta) a).sayHello();
上面的代码对编译器有效,但在运行时,你会得到一个异常,因为从 到 的强制转换是不兼容的。Beta
Charlie
与此同时,回到PHP农场。
以下内容对 PHP 编译器有效 - 它会很乐意将其转换为可执行字节代码,但您将收到运行时错误:
class Alpha {}
class Beta extends Alpha {
function sayHello() {
print "Hello";
}
}
$a = new Alpha();
$a->sayHello();
这是因为 PHP 变量没有类型。编译器不知道哪些运行时类型对变量有效,因此它不会尝试强制执行它。您也不会像在 Java 中那样显式指定类型。是的,有类型提示,但这些只是运行时协定。以下内容仍然有效:
// reuse the classes from above
function tellToSayHello(Alpha $a) {
$a->sayHello();
}
tellToSayHello(new Beta());
即使 PHP 变量没有类型,这些值仍然有类型。PHP的一个特别有趣的方面是可以更改值的类型。例如:
// 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"
此功能有时与类型转换混淆,但这是用词不当。类型仍然是值的属性,类型更改发生在运行时 - 而不是在编译时。
在PHP中,更改类型的能力也非常有限。只能在简单类型之间更改类型,而不能更改对象。因此,无法将类型从一个类更改为另一个类。您可以创建新对象并复制状态,但无法更改类型。PHP在这方面有点局外人;其他类似的语言将类视为比PHP更动态的概念。
PHP的另一个类似功能是,您可以将值克隆为新类型,如下所示:
// 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"
从语法上讲,这看起来很像静态类型语言中编写类型转换的方式。因此,它也经常与类型转换混淆,即使它仍然是运行时类型转换。
总结一下:类型强制转换是更改变量类型(而不是值)的操作。由于变量在PHP中没有类型,因此不仅不可能做到,而且首先要问这是一件荒谬的事情。
虽然不需要在 PHP 中键入强制转换,但您可能会遇到想要将父对象转换为子对象的情况。
//Example of a sub class
class YourObject extends MyObject {
public function __construct(MyObject $object) {
foreach($object as $property => $value) {
$this->$property = $value;
}
}
}
$my_object = new MyObject();
$your_object = new YourObject($my_object);
因此,您所要做的就是将父对象向下传递给子对象的构造函数,并让构造函数复制属性。您甚至可以根据需要过滤/更改它们。
//Class to return standard objects
class Factory {
public static function getObject() {
$object = new MyObject();
return $object;
}
}
//Class to return different object depending on the type property
class SubFactory extends Factory {
public static function getObject() {
$object = parent::getObject();
switch($object->type) {
case 'yours':
$object = new YourObject($object);
break;
case 'ours':
$object = new OurObject($object);
break;
}
return $object;
}
}
//Example of a sub class
class YourObject extends MyObject {
public function __construct(MyObject $object) {
foreach($object as $property => $value) {
$this->$property = $value;
}
}
}
它不是类型转换,但它可以满足您的需要。