我有一些共享某些属性的类,我想做类似的事情:
$dog = (Dog) $cat;
是否有可能或有任何通用的工作?
它不是超类,或接口或以任何方式相关。他们只是2个不同的类我想php将猫类的属性映射到狗并给我新的对象。 -
我想我必须指出更多一点,因为这似乎是一件毫无意义的事情。
我从不同的父类继承的类导致我根据保存方法创建了一个继承树,也许从一开始就是我的坏,但问题是我有很多类实际上相同但是与mysql交互一个,与xml文件交互另一个。所以我有:
class MySql_SomeEntity extends SomeMysqlInteract{}
和
Xml_SomeEntity extends SomeXmlInteract{}
它有点深一点,但问题就在于此。我不能让他们从同一个类继承导致不允许多重继承,并且我不能将当前与超级语言的交互分开导致将是一个大麻烦。
基本上每个属性都是实用的。
因为我有很多这样的匹配类,我想做一些通用的转换或类似的东西可以转换(将值传递给每个属性),但我试图以最简单的方式搜索这个类的每个人。
答案 0 :(得分:30)
PHP中没有用于定义用户定义对象的类型转换的内置方法。也就是说,这里有几种可能的解决方案:
1)使用类似下面的函数对对象进行反序列化,更改字符串,以便在反序列化后将所需的属性包含在新对象中。
function cast($obj, $to_class) {
if(class_exists($to_class)) {
$obj_in = serialize($obj);
$obj_out = 'O:' . strlen($to_class) . ':"' . $to_class . '":' . substr($obj_in, $obj_in[2] + 7);
return unserialize($obj_out);
}
else
return false;
}
2)或者,您可以使用反射/手动迭代它们或使用get_object_vars()复制对象的属性。
This article应该启发你“PHP的黑暗角落”并在用户层面实现类型转换。
答案 1 :(得分:30)
您可以使用上面的函数来投射不相似的类对象(PHP> = 5.3)
/**
* Class casting
*
* @param string|object $destination
* @param object $sourceObject
* @return object
*/
function cast($destination, $sourceObject)
{
if (is_string($destination)) {
$destination = new $destination();
}
$sourceReflection = new ReflectionObject($sourceObject);
$destinationReflection = new ReflectionObject($destination);
$sourceProperties = $sourceReflection->getProperties();
foreach ($sourceProperties as $sourceProperty) {
$sourceProperty->setAccessible(true);
$name = $sourceProperty->getName();
$value = $sourceProperty->getValue($sourceObject);
if ($destinationReflection->hasProperty($name)) {
$propDest = $destinationReflection->getProperty($name);
$propDest->setAccessible(true);
$propDest->setValue($destination,$value);
} else {
$destination->$name = $value;
}
}
return $destination;
}
实施例
class A
{
private $_x;
}
class B
{
public $_x;
}
$a = new A();
$b = new B();
$x = cast('A',$b);
$x = cast('B',$a);
答案 2 :(得分:3)
如果不使用继承(如mentioned by author),您似乎正在寻找一种解决方案,可以transform
一个类到另一个类,并且开发人员的预先知道并理解2的相似性类强>
对于对象之间的转换,没有现成的解决方案。您可以尝试的是:
答案 3 :(得分:2)
听起来你真正想做的是实现interface。
您的界面将指定对象可以处理的方法,当您将实现该接口的对象传递给需要支持该接口的对象的方法时,您只需键入带有该接口名称的参数。
答案 4 :(得分:1)
你不需要施法。一切都充满活力。
我有课程折扣
我有几个类扩展了这个类:
ProductDiscount
StoreDiscount
ShippingDiscount
......
我在代码的某处:
$pd = new ProductDiscount();
$pd->setDiscount(5, ProductDiscount::PRODUCT_DISCOUNT_PERCENT);
$pd->setProductId(1);
$this->discounts[] = $pd;
.....
$sd = new StoreDiscount();
$sd->setDiscount(5, StoreDiscount::STORE_DISCOUNT_PERCENT);
$sd->setStoreId(1);
$this->discounts[] = $sd;
我的某个地方:
foreach ($this->discounts as $discount){
if ($discount->getDiscountType()==Discount::DISCOUNT_TYPE_PRODUCT){
$productDiscount = $discount; // you do not need casting.
$amount = $productDiscount->getDiscountAmount($this->getItemTotalPrice());
...
}
}// foreach
其中getDiscountAmount是ProductDiscount特定函数,而getDiscountType是Discount特定函数。
答案 5 :(得分:1)
更好的方法:
class Animal
{
private $_name = null;
public function __construct($name = null)
{
$this->_name = $name;
}
/**
* casts object
* @param Animal $to
* @return Animal
*/
public function cast($to)
{
if ($to instanceof Animal) {
$to->_name = $this->_name;
} else {
throw(new Exception('cant cast ' . get_class($this) . ' to ' . get_class($to)));
return $to;
}
public function getName()
{
return $this->_name;
}
}
class Cat extends Animal
{
private $_preferedKindOfFish = null;
public function __construct($name = null, $preferedKindOfFish = null)
{
parent::__construct($name);
$this->_preferedKindOfFish = $preferedKindOfFish;
}
/**
* casts object
* @param Animal $to
* @return Animal
*/
public function cast($to)
{
parent::cast($to);
if ($to instanceof Cat) {
$to->_preferedKindOfFish = $this->_preferedKindOfFish;
}
return $to;
}
public function getPreferedKindOfFish()
{
return $this->_preferedKindOfFish;
}
}
class Dog extends Animal
{
private $_preferedKindOfCat = null;
public function __construct($name = null, $preferedKindOfCat = null)
{
parent::__construct($name);
$this->_preferedKindOfCat = $preferedKindOfCat;
}
/**
* casts object
* @param Animal $to
* @return Animal
*/
public function cast($to)
{
parent::cast($to);
if ($to instanceof Dog) {
$to->_preferedKindOfCat = $this->_preferedKindOfCat;
}
return $to;
}
public function getPreferedKindOfCat()
{
return $this->_preferedKindOfCat;
}
}
$dogs = array(
new Dog('snoopy', 'vegetarian'),
new Dog('coyote', 'any'),
);
foreach ($dogs as $dog) {
$cat = $dog->cast(new Cat());
echo get_class($cat) . ' - ' . $cat->getName() . "\n";
}
答案 6 :(得分:1)
如果您尝试从或转换的对象具有属性也是用户定义的类,并且您不想进行反射,则可以使用此对象。
<?php
declare(strict_types=1);
namespace Your\Namespace\Here
{
use Zend\Logger; // or your logging mechanism of choice
final class OopFunctions
{
/**
* @param object $from
* @param object $to
* @param Logger $logger
*
* @return object
*/
static function Cast($from, $to, $logger)
{
$logger->debug($from);
$fromSerialized = serialize($from);
$fromName = get_class($from);
$toName = get_class($to);
$toSerialized = str_replace($fromName, $toName, $fromSerialized);
$toSerialized = preg_replace("/O:\d*:\"([^\"]*)/", "O:" . strlen($toName) . ":\"$1", $toSerialized);
$toSerialized = preg_replace_callback(
"/s:\d*:\"[^\"]*\"/",
function ($matches)
{
$arr = explode(":", $matches[0]);
$arr[1] = mb_strlen($arr[2]) - 2;
return implode(":", $arr);
},
$toSerialized
);
$to = unserialize($toSerialized);
$logger->debug($to);
return $to;
}
}
}
答案 7 :(得分:0)
您可以考虑工厂
class XyFactory {
public function createXyObject ($other) {
$new = new XyObject($other->someValue);
// Do other things, that let $new look like $other (except the used class)
return $new;
}
}
否则,user250120s解决方案是唯一一个接近类强制转换的解决方案。
答案 8 :(得分:0)
class It {
public $a = '';
public function __construct($a) {
$this->a = $a;
}
public function printIt() {
;
}
}
//contains static function to 'convert' instance of parent It to sub-class instance of Thing
class Thing extends it {
public $b = '';
public function __construct($a, $b) {
$this->a = $a;
$this->b = $b;
}
public function printThing() {
echo $this->a . $this->b;
}
//static function housed by target class since trying to create an instance of Thing
static function thingFromIt(It $it, $b) {
return new Thing($it->a, $b);
}
}
//create an instance of It
$it = new It('1');
//create an instance of Thing
$thing = Thing::thingFromIt($it, '2');
echo 'Class for $it: ' . get_class($it);
echo 'Class for $thing: ' . get_class($thing);
返回:
Class for $it: It
Class for $thing: Thing
答案 9 :(得分:0)
我认为最好的方法是创建一个类的新实例,然后分配该对象。这就是我要做的事情:
public function ($someVO) {
$someCastVO = new SomeVO();
$someCastVO = $someVO;
$someCastVO->SomePropertyInVO = "123";
}
执行此操作将为您提供大多数IDE中的代码提示,并帮助确保您使用正确的属性。
答案 10 :(得分:0)
PHP通过使用以下方法提供了一种非常简单的方法:
(object) ['id'=>1,'name'=>'cat']
您可以尝试以下方法:
$dog = json_encode($dog);
$cat = json_decode($dog)
答案 11 :(得分:0)
您可以在下面选择此示例。希望对您有所帮助。
/** @var ClassName $object */
$object->whateverMethod() // any method defined in the class can be accessed by $object
我知道这不是强制转换,但有时可能有用。