Nasıl ben onun ebeveynin ebeveynin kurucusunu çağırmak için bir PHP sınıfı kurucu alabilirim

9 Cevap php

Ben ana kurucu çağırmadan PHP bir sınıf yapıcısı, ebeveynin parent's (büyükbaba?) Kurucu çağırmak olması gerekir.

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {

    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        // THIS IS WHERE I NEED TO CALL GRANDPA'S
        // CONSTRUCTOR AND NOT PAPA'S
    }
}

Bunu yapmak için tuhaf bir şey olduğunu biliyorum ve ben kötü koku ama eğer mümkünse yine de, ben merak ediyorum olmayan bir çare bulmak için çalışılıyor.

EDIT

Ben seçilmiş cevap için gerekçe göndermek gerektiğini düşündüm. Nedeni olarak; tüm değerlerini koruyarak "büyükbaba" kurucusunu çağırmak isteyen sorununa solutionto en zarif. Bu kesinlikle iyi bir yaklaşım değil ne de dost OOP, ama bu soru soran ne değil.

Daha sonraki bir tarihte, bu soru karşısında gelecek herkes için - Please find another solution. Ben sınıf yapısı üzerinde büyük hasara yol yoktu çok daha iyi bir yaklaşım bulmak mümkün oldu. Böylece gerekir.

9 Cevap

Çirkin geçici çözüm bunu yapıcısında içerdiği kodu ayrıştırmak istemeyen belirten Papa bir boolean param geçmek olacaktır. yani:

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {

    }

}

class Papa extends Grandpa
{
    public function __construct($bypass = false)
    {
        // only perform actions inside if not bypassing
        if (!$bypass) {

        }
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        $bypassPapa = true;
        parent::__construct($bypassPapa);
    }
}

Sen Grandpa::__construct(), bunun için başka bir kısayol var kullanmanız gerekir. Ayrıca, bu Papa sınıfının kapsüllenmesini kalıntıları - okuma veya Papa, bu __construct() yöntemi sırasında denilen olacağını varsaymak güvenli olmalıdır üzerinde çalışırken inşaat, ama Kiddo class yapmaz.

Ben sorunu çözüldü alternatif bir çözüm ile geliyor sona erdi.

  • Dedemi genişletilmiş bir ara sınıf oluşturduk.
  • Sonra Papa ve ufaklık hem de bu sınıfı uzatıldı.
  • Kiddo Papa bazı ara işlevselliğini gerekli ama öyle sınıf, ek işlevsellik ve de bunu uzatmak var yapıcısının gibi değildi.

Ben daha çirkin bir soru için henüz geçerli çirkin çözümler sağlanan diğer iki cevapları upvoted ettik :)

Bir bayrak kullanmak değildir ve sizin durumunuzda işe yarayabilecek başka bir seçenek:

<?php
// main class that everything inherits
class Grandpa 
{
    public function __construct(){
        $this->GrandpaSetup();
    }

    public function GrandpaSetup(){
        $this->prop1 = 'foo';
        $this->prop2 = 'bar';
    }
}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
        $this->prop1 = 'foobar';
    }

}
class Kiddo extends Papa
{
    public function __construct()
    {
        $this->GrandpaSetup();
    }
}

$kid = new Kiddo();
echo "{$kid->prop1}\n{$kid->prop2}\n";

Bunun için daha kolay bir çözüm var, ama sizin mevcut sınıf geçti tam olarak ne kadar miras bilmesini gerektirir. Neyse ki, get_parent_class () 'ler argümanlar sınıf dizinin üyesi bir dize olarak sınıf ismi gibi bir örneğinin kendisi olmasına izin.

Bir miras nesnenin instanced kapsamında bu özel durumda fark (ah, PHP) ihmal edilebilir olsa bu da doğal olarak, statik bir sınıf '__ construct () yöntemi çağrılarak dayanır unutmayın.

Aşağıdaki düşünün:

class Foo {
    var $f = 'bad (Foo)';

    function __construct() {
        $this->f = 'Good!';
    }
}

class Bar extends Foo {
    var $f = 'bad (Bar)';
}

class FooBar extends Bar {
    var $f = 'bad (FooBar)';

    function __construct() {
        # FooBar constructor logic here
        call_user_func(array(get_parent_class(get_parent_class($this)), '__construct'));
    }
}

$foo = new FooBar();
echo $foo->f; #=> 'Good!'

Yine, bu kadar miras nedeniyle debug_backtrace (sınırlamaları, yerini almıştır nasıl hiçbir fikrim yok bir durumda) için uygun bir çözüm değildir, ama planlandığı gibi kontrollü koşullarda, işe yarıyor.

İstediğiniz yerden Büyükbaba :: __construct arayabilirler $ this anahtar geçerli sınıf örneğine sevk edecektir. But be carefull with this method you cannot access to protected properties and methods of current instance from this other context, only to public elements. => Tüm iş ve officialy supported.

Örnek

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {
        echo $this->one; // will print 1
        echo $this->two; // error cannot access protected property
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public $one = 1;
    protected $two = 2;
    public function __construct()
    {
        Grandpa::__construct();
    }
}

new Kiddo();

Ben bu deneyin, "çok fazla php" katılıyorum:

class Büyükbaba 
{
    public function __construct()
    {
        echo 'Büyükbaba<br/>';
    }

}

class Papa extends Büyükbaba
{
    public function __construct()
    {
        echo 'Papa<br/>';
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        // THIS IS WHERE I NEED TO CALL GRANDPA'S
        // CONSTRUCTOR AND NOT PAPA'S
        echo 'Kiddo<br/>';
        Büyükbaba::__construct();
    }
}

$instance = new Kiddo;

Beklendiği gibi sonuç var:

Kiddo

Büyükbaba

Bu bir özellik değil, bir hata, referans için bu kontrol etmektir:

https://bugs.php.net/bug.php?id=42016

Bu işler sadece yoludur. Bunun doğru bağlam geliyor görürse bu çağrı versiyonu statik bir çağrı zorlamaz.

Bunun yerine sadece $ this tutmak ve onunla mutlu olacak.

parent :: yöntem () aynı şekilde çalışır, statik olarak yöntemi tanımlamak zorunda değilsiniz ama aynı bağlamda çağrılabilir. Daha ilginç için bu deneyin:

class Büyükbaba 
{
    public function __construct()
    {
        echo 'Büyükbaba<br/>';
        Kiddo::hello();
    }

}

class Papa extends Büyükbaba
{
    public function __construct()
    {
        echo 'Papa<br/>';
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        // THIS IS WHERE I NEED TO CALL GRANDPA'S
        // CONSTRUCTOR AND NOT PAPA'S
        echo 'Kiddo<br/>';
        Büyükbaba::__construct();
    }

    public function hello()
    {
        echo 'Merhaba<br/>';
    }
}

$instance = new Kiddo;

Beklendiği gibi de çalışıyor:

Kiddo

Büyükbaba

Merhaba

Yeni Papa başlatmaya çalıştığınızda Ama eğer bir E_STRICT hata alırsınız:

$papa = new Papa;

Sıkı standartları: Non-statik metot Evlat :: hello () uyumsuz bağlamından $ bu varsayarak, statik denilen olmamalı

Bir üst yöntemi bir Çocuk :: yöntem () çağırabilirsiniz olmadığını belirlemek için instanceof kullanabilirsiniz:

if ($this instanceof Kiddo) Kiddo::hello();

Tamam, Yine bir başka çirkin çözüm:

Papa bir işlevi gibi oluşturun:

protected function call2Granpa() {
     return parent::__construct();
}

Sonra Kiddo olarak kullanmak:

parent::call2Granpa(); / / yerine Papa kurucu çağırmak.

I think it could work... I haven't test it, so I'm not sure if the objects are created correctly.

Ben bu yaklaşımı kullanmış ancak non-yapıcı işlevleri ile.

// main class that everything inherits
class Grandpa 
{
    public function __construct()
    {
        $this->___construct();
    }

    protected function ___construct()
    {
        // grandpa's logic
    }

}

class Papa extends Grandpa
{
    public function __construct()
    {
        // call Grandpa's constructor
        parent::__construct();
    }
}

class Kiddo extends Papa
{
    public function __construct()
    {
        parent::___construct();
    }
}

"___construct" bazı sihirli adı değil unutmayın, siz "doGrandpaStuff" çağırabilirsiniz.