Ortak bir ebeveyn ile sınıflar arasında dönüştürmek mümkün mü?

3 Cevap php

Ben her bir ortak ebeveyn uzatmak iki sınıf varsa, aralarında dönüştürmek mümkün mü?

class Foo
{

    public $bar;


}

class FooDatabase extends Foo
{

    public function load() {}

    public function save() {}

}

class FooFlatfile extends Foo
{

    public function load() {}

    public function save() {}

}

$foo = new FooDatabase;
$foo->bar = 'elf';

Bir örnek olarak bu kodu kullanarak, ben özelliğinin değerini koruyarak {[(3), FooDatabase için FooFlatfile örneğinden $foo dönüştürmek istiyorum }].

Edit: Aslında bunu yaparken pratikte böyle harika bir fikir olmadığını fark yoktur. Aksine, ben bu potansiyel bir düzeltme olduğu bir duruma geldi, ve onu elde nasıl olabilir merak oldu.

3 Cevap

Tavsiye olmasa da bu mümkün. A dark corner of PHP: class casting bir göz atın. Temelde:

  1. Sınıf seri;
  2. Tefrika halinde sınıf adını değiştirin; o zaman
  3. Bu serisini.

Evet, bu kesmek.

Büyük soru: neden bunu yapmak istiyorsun nedir? Eğer sınıfını değiştirmek için ihtiyaç varsa, nesne modeli kötü olduğunu çok güçlü bir göstergedir. Onlar vermek için kullanılan tanıtım OO eski örneklerinden hatırlatıyor:

  • Kişi sınıfı;
  • Satıcı Kişi uzanır;
  • Yöneticisi Kişi uzanır.

aynı nedenle bir horrible örneği: Birisi Yöneticisi Satıcının değişir ne olur? Kompozisyon tabanlı yaklaşım ile karşılaştırın nerede Kişi has-a İş (Yöneticisi ve Satıcı örnekleri veya Job alt sınıfları nerede). Çok daha sağlıklı bir yaklaşım.

Son olarak, ben değiştiremem bazı kod bunu yapmak için sizi zorluyor ise, adaptör veya cephe çeşit kullanarak kapalı iyi olurdu ekleyeceğiz:

class A { ... }
class B {
  public function asA() {
    $ret = new A;
    // configure;
    return $ret;
  }
  ...
}

Yine bu çok daha sağlam otomatik özellik kopyalama sınıf değiştirme işlemi herhangi bir tür daha.

Eğer bir yenisini oluşturmak ve değerleri üzerinde kopyalayarak gerekenleri başarmak miyim?

$foo2 = new FooFlatFile;
$foo2 = foo->bar;

Ne gerek halletmek vermezse, bize daha ayrıntılı bilgi verin.

Yorum yanıt:

Eğer sık ​​sık yapmayı planlıyorsanız, bu dizi veya yapı çeşit tüm üyelerini dönmek için bir üye işlevi oluşturmak için kolay olurdu. Ancak, bu noktada, gerçekten kendinize sormanız gereken "neden bunu yapıyorum?" Diğer cevap düzenli olarak bunu yapmak isteyen varsa, size çok kötü sınıfları tasarlanmış olduğunu söyleyerek üzerinde bir noktadır.

Eğer arasında geçiş yapmak isteyen iki sınıfları var ise, onları ayıran ne kaldırmak ve bir sınıf yapmak. Onlar aralarında geçiş paçayı düşüren durumda, temelde aynıdır, ama sen çok daha iyi sadece bir sınıf yapma ile hizmet olacaktır ya.

Yoksa onlar hala iki sınıfları gerekir bu durumda, birbirinden temelde farklıdır. Eğer bir veritabanı var ve düz bir dosyaya çevirmek için çalışıyorsanız, bir ihracat fonksiyonu düz bir veri içine veritabanına çevirmek olması gerekir. Bir anlamlı, kullanışlı bir şekilde veri verim olmaz: dinamik olarak değişen sınıflar Oracle dosyasını açmak için Not Defteri'ni kullanarak gibi olurdu. Aralarında gitmek için, 'ihracat' ve birbirleriyle aynı veri yapısını kullanmak 'import' yazma fonksiyonlarını. Sen yeni bir yenisini, eski gelen ihracat, ithalat oluşturmak ve eski silin.

Ben bunu yapmak için mantıklı bir senaryo hayal bile edemiyorum, çünkü ben, açıkçası söylemek başka ne emin değilim. Eğer çözmek için çalışıyoruz ne geçmişi hakkında daha fazla ayrıntı verebilir, ben daha iyi tavsiye verebilir.

Sen böyle bir şey yapabilirsiniz, bazı sınırlamaları vardır (kurucular türleri üzerine sınırları ve özel değişkenler kopyalamak olamaz) ama çalışmak için yapılabilir.

class Foo {
  public $bar;

  protected function convertTo($classname) {
    $rc_other_class = new ReflectionClass($classname);
    if ($rc_other_class->isSubclassOf(get_class())) {
      // there's a limitation here in that the constructor can't take params
      $other_class = new $classname();
      $rc_this_class = new ReflectionClass(get_class());
      $properties = $rc_this_class->getProperties();
      foreach ($properties as $property) {
        if (!$property->isStatic() &&
            $property->getDeclaringClass()->getName() == get_class()) {
          $property = $property->getName();
          if (property_exists($this, $property)) {
            // this will throw if you try to copy a private var, add a filter to
            // getProperties to prevent this but you probably want the error
            $other_class->$property = $this->$property;
          }
        }
      }
    } else {
      return false;
    }
  }
}