Ive некоторые кланы, которые имеют некоторые атрибуты, и я хотел бы сделать что-то вроде: $ dog = (Dog) $ cat;
возможно ли это или существует какая-то общая работа?
Это не суперкласс, ни интерфейс, ни связанные с ним. Они всего лишь две разные кланы, я хотел бы, чтобы php сопоставлял атрибуты от класса кошки собаке и давал мне новый объект. –
я предполагаю, что я должен указать немного больше причин, кажущихся бессмысленными.
ive clases, которые наследуются от разных родительских кланов, вызывают, что ive создало дерево наследования, основанное на методе сохранения, возможно, мое плохое с самого начала, но проблема в том, что у меня есть много кланов, которые практически равны, но взаимодействуют с mysql и другим с файлами xml. поэтому у меня есть: класс MySql_SomeEntity extends SomeMysqlInteract {} и Xml_SomeEntity расширяет SomeXmlInteract {} его немного более глубокое дерево, но проблема его в этом. я не могу заставить их наследовать от одного и того же класса, потому что многоуровневое наследование не оговорено, и я не могу разделить текущее взаимодействие с суперклассами, потому что это будет большой проблемой.
В принципе, атрибуты в каждом из них практичны одинаково.
так как у меня много таких махинаций, я бы хотел сделать какое-то общее литье или что-то подобное, которое может конвертировать (передать значения каждому атрибуту), но я пытаюсь найти самый простой способ для всех этих кланов.
В 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 ().
Эта статья должна просветить вас на «темных углах PHP» и реализовать типизацию на уровне пользователя.
Вы можете использовать вышеприведенную функцию для отливки не похожих объектов класса (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);
Без использования наследования (как упоминалось автором ) кажется, что вы ищете решение, которое может transform
один класс в другой, при условии, что разработчик знает и понимает сходство двух классов .
Нет никакого существующего решения для преобразования между объектами. Что вы можете попробовать:
Похоже, что вы действительно хотите реализовать интерфейс .
В вашем интерфейсе будут указаны методы, которые может обрабатывать объект, и когда вы передаете объект, реализующий интерфейс, методу, который хочет объект, поддерживающий интерфейс, просто введите аргумент с именем интерфейса.
Вам не нужно кастинг. Все динамично.
У меня есть скидка класса.
У меня есть несколько классов, которые расширяют этот класс:
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 – специальная функция скидок.
лучший aproach:
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"; }
Вы можете думать о фабриках
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 является единственным, что близко к классу.
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
Я считаю, что лучший подход – просто создать новый экземпляр класса и назначить объект. Вот что я сделал бы:
public function ($someVO) { $someCastVO = new SomeVO(); $someCastVO = $someVO; $someCastVO->SomePropertyInVO = "123"; }
Выполнение этого даст вам подсказку кода в большинстве IDE и поможет убедиться, что вы используете правильные свойства.