PHP fazla 1 sınıfını kullanarak bir sınıf uzatabilir miyim?

11 Cevap php

Ben gerekir ama organizasyon için ayrı ayrı saklamak istediğiniz fonksiyonları ile çeşitli sınıfları varsa, ben de var bir sınıf uzatabilirsiniz?

yani class a extends b extends c

edit: Ben sınıfları bir anda uzatmak için nasıl biliyorum, ama ben anında birden fazla baz sınıfları kullanarak bir sınıfı genişletmek için bir yöntem arıyorum - AFAIK PHP bunu yapamam ama başvurmadan etrafında yolu olmalı class c extends b, class b extends a

11 Cevap

Katkınızı cevaplama:

Eğer gerçekten sahte çoklu miras istiyorsanız, size sihirli bir işlev __ çağrısı () kullanabilirsiniz.

Bu sınıftan bakış Bir kullanıcının noktasını çalışıyor olsa da bu çirkin:

class B {
    public function method_from_b($s) {
    	echo $s;
    }
}

class C {
    public function method_from_c($s) {
    	echo $s;
    }
}

class A extends B
{
  private $c;

  public function __construct()
  {
    $this->c = new C;
  }

  // fake "extends C" using magic function
  public function __call($method, $args)
  {
    $this->c->$method($args[0]);
  }
}


$a = new A;
$a->method_from_b("abc");
$a->method_from_c("def");

Baskılar "abcdef"

İki temel sınıfları genişleten bir sınıf olamaz. Sen olamazdı.

// this is NOT allowed (for all you google speeders)
Matron extends Nurse, HumanEntity

Aşağıdaki gibi ancak bir hiyerarşi var olabilir ...

Matron extends Nurse    
Consultant extends Doctor

Nurse extends HumanEntity
Doctor extends HumanEntity

HumanEntity extends DatabaseTable
DatabaseTable extends AbstractTable

ve benzerleri.

Yakında mix-ins eklemek için planları vardır, ben inanıyorum.

Ama o zamana kadar, kabul edilen yanıt ile gitmek. You can soyut olduğunu, bir "uzatılabilir" class yapmak biraz:

class Extendable{
  private $extender=array();

  public function addExtender(Extender $obj){
    $this->extenders[] = $obj;
    $obj->setExtendee($this);
  }

  public function __call($name, $params){
    foreach($this->extenders as $extender){
       //do reflection to see if extender has this method with this argument count
       if (method_exists($extender, $name)){
          return call_user_func_array(array($extender, $name), $params);
       }
    }
  }
}


$foo = new Extendable();
$foo->addExtender(new OtherClass());
$foo->other_class_method();

Bu modelde o "OtherClass" yaklaşık $ foo 'bilmek' alır unutmayın. OtherClass bu ilişkiyi kurmak için "setExtendee" adında bir kamu görevi olması gerekir. Bu yöntemler $ foo çağrılması eğer Ardından, bu dahili $ foo erişebilirsiniz. Ancak, bir gerçek genişletilmiş sınıf yaptığınız gibi herhangi bir özel / korumalı yöntemler / değişkenlere erişim almazsınız.

Sınıflar yöntemlerden sadece koleksiyonları olması demek değildir. A sınıfı durumunu değiştirir devlet (alanlar) ve davranış (yöntemleri) hem de, soyut bir kavramı temsil etmek gerekiyordu. Sadece bazı istenen davranışı almak için devralmayı kullanarak kötü OO tasarım gibi geliyor, ve pek çok dil birden çok devralma vermemek neden tam olarak nedeni: "spagetti miras", yani her ihtiyacınız olan bir yöntemi vardır çünkü 3 sınıfları uzanan, ve ile biten önlemek amacıyla 100 yöntemi ve 20 alanlarını devralan bir sınıf, ama sadece hiç 5 tanesi kullanır.

Umarım, PHP 5.4 'dan satışa sunulacak, özellikleri, kullanabilirsiniz.

Özellikleri PHP gibi tek miras dilinde kod yeniden kullanım için bir mekanizmadır. A Sürekli farklı bir sınıf hiyerarşileri yaşayan birkaç bağımsız sınıflara serbestçe yöntemleri setleri yeniden bir geliştirici sağlayarak tek miras bazı sınırlamaları azaltmak için tasarlanmıştır. Özellikleri ve sınıfların kombinasyonunun semantik karmaşıklığını azaltır ve birden çok devralma ve Mixins ile ilgili problemleri ortadan kaldırır, tipik bir biçimde, içinde tanımlanmıştır.

Bunlar Perl 6, Squeak, Scala, Slate ve Kalesi gibi dillerin yeni sürümlerinde dolayısıyla entegrasyon, iyi kompozisyon ve yeniden destekleme potansiyeli için tanınır. Özellikleri aynı zamanda Java ve C # taşıdık edilmiştir.

Daha fazla bilgi: https://wiki.php.net/rfc/traits

Ben sadece benim "çoklu kalıtım" sorunu çözüldü:

class Session {
    public $username;
}

class MyServiceResponsetype {
    protected $only_avaliable_in_response;
}

class SessionResponse extends MyServiceResponsetype {
    /** has shared $only_avaliable_in_response */

    public $session;

    public function __construct(Session $session) {
      $this->session = $session;
    }

}

Bu şekilde ben MyServiceResponsetype yine kendisi tarafından Oturumu idare edememek uzanan bir SessionResponse içinde oturumu işlemek için güce sahip.

PHP henüz çoklu sınıf mirası desteklemez, bununla birlikte birden fazla arabirimi devralma desteklemiyor.

http://www.hudzilla.org/php/6_17_0.php bazı örnekler için bkz.

PHP birden çok devralma izin vermez, ama birden arayüzleri uygulama ile yapabilirsiniz. Uygulama "ağır" ise, ayrı bir sınıfta her arayüz için skeletal implementation sağlar. Sonra olabilir delegate all interface class to these skeletal implementations aracılığı object containment.

Size ulaşmak için çalışıyoruz tam olarak ne olduğunu bilerek değil, ben bu durumda kompozisyon yerine miras kullanmayı size uygulamayı yeniden tasarlama imkanı bakarak öneririz.

Her zaman iyi bir fikir yani ebeveyn için bu tüm işlevler eklemek ... fonksiyonları ile, üst sınıf yapmaktır.

Ve hiyerarşik bu aşağı kullanan tüm sınıfları "hareket". Özgü yeniden yazma fonksiyonları, - ihtiyacım.

http://stackoverflow.com/a/4160928/2226755: Bir fonksiyon kamuoyu bu konuyu görmek olup olmadığını kontrol etmek istiyorsanız

Ve birçok veya argümanlar için (...) yöntemini call_user_func_array kullanın.

Bu gibi:

class B {
    public function method_from_b($s) {
        echo $s;
    }
}

class C {
    public function method_from_c($l, $l1, $l2) {
        echo $l.$l1.$l2;
    }
}

class A extends B {
    private $c;

    public function __construct() {
        $this->c = new C;
    }

    public function __call($method, $args) {
        if (method_exists($this->c, $method)) {
            $reflection = new ReflectionMethod($this->c, $method);
            if (!$reflection->isPublic()) {
                throw new RuntimeException("Call to not public method ".get_class($this)."::$method()");
            }

            return call_user_func_array(array($this->c, $method), $args);
        } else {
            throw new RuntimeException("Call to undefined method ".get_class($this)."::$method()");
        }
    }
}


$a = new A;
$a->method_from_b("abc");
$a->method_from_c("d", "e", "f");