簡體   English   中英

訪問父變量和子變量在父定義的方法中 - PHP

[英]Access parent and child variables in method defined in parent - PHP

我有一個從父對象繼承的子對象。 兩者都有一個靜態變量,它在每個對象中都有不同的值; 當我實例化子項時,我想將該變量從父項和子項添加到數組中。 為了節省重復的代碼,我在父類中編寫了一個方法( addFoo ),該方法從父類和子類構造函數中調用。 但是,我似乎無法找到一種方法來區分從子構造函數調用父構造函數時的調用(如下所示,無論使用$this self ,方法的輸出在兩種情況下都是相同的)或static )。

class A {
    public static $foo = 'foo';
    
    public $thisvars = array();
    public $selfvars = array();
    public $staticvars = array();
    
    public function __construct() {
        $this->addFoo();
    }
    
    public function addFoo() {
        $this->selfvars[] = self::$foo;
        $this->staticvars[] = static::$foo;
        $this->thisvars[] = $this::$foo;
    }
    
}

class B extends A {
    public static $foo = 'bar';
    
    public function __construct() {
        parent::__construct();
        $this->addFoo();
    }
}

$b = new B;
print_r($b->selfvars);
print_r($b->staticvars);
print_r($b->thisvars);

輸出:

Array
(
    [0] => foo
    [1] => foo
)
Array
(
    [0] => bar
    [1] => bar
)
Array
(
    [0] => bar
    [1] => bar
)

我可以通過將調用類傳遞給addFoo函數(見下文)來解決這個問題,但是有沒有更好的(正確的?)方法嗎?

class C {
    public static $foo = 'foo';
    
    public $vars = array();
    
    public function __construct() {
        $this->addFoo(__CLASS__);
    }
    
    public function addFoo($class) {
        $this->vars[] = $class::$foo;
    }
    
}

class D extends C {
    public static $foo = 'bar';
    
    public function __construct() {
        parent::__construct();
        $this->addFoo(__CLASS__);
    }
}

$d = new D;
print_r($d->vars);

輸出:

Array
(
    [0] => foo
    [1] => bar
)

3v4l.org 上的演示

不是讓每個子構造函數都調用addFoo ,一種方法是在基構造函數調用的基類中使用單個addFoos方法,該方法將從后期靜態綁定類開始附加所有$foo值:

class A
{
    public static $foo = 'foo';

    public $vars = [];

    public function __construct()
    {
        $this->addFoos();
    }

    private function addFoos()
    {
        $class = static::class;
        do {
            $this->vars[] = $class::$foo;
        } while ($class = get_parent_class($class));
    }

}

class B extends A
{
    public static $foo = 'bar';
}

class C extends B
{
    public static $foo = 'baz';
}

$a = new A;
print_r($a->vars);  // ['foo']

$b = new B;
print_r($b->vars);  // ['bar', 'foo']

$c = new C;
print_r($c->vars);  // ['baz', 'bar', 'foo']

該方法被標記為private因為在這種情況下它不應該被擴展(也不應該從外部調用)。

演示

我或者會考慮另一種更直接的方法:

class A
{
    public static $foo = 'foo';

    public function getVars()
    {
        return [self::$foo];
    }
}

class B extends A
{
    public static $foo = 'bar';

    public function getVars()
    {
        return array_merge(parent::getVars(), [self::$foo]);
    }
}

class C extends B
{
    public static $foo = 'baz';

    public function getVars()
    {
        return array_merge(parent::getVars(), [self::$foo]);
    }
}

$a = new A;
print_r($a->getVars());  // ['foo']

$b = new B;
print_r($b->getVars());  // ['foo', 'bar']

$c = new C;
print_r($c->getVars());  // ['foo', 'bar', 'baz']

在這種情況下,您確實必須在每個子類上重新定義getVars ,但畢竟,每個類決定應該公開哪些變量是有意義的。 在此過程中,您的代碼變得不那么晦澀/更易於維護。

如果一個類不需要/想要“貢獻”,您可以簡單地省略getVars的靜態屬性和getVars擴展。

演示

筆記:

  • 如果需要,您可以輕松地將變量緩存到A$vars屬性中,
  • 順序是從另一個答案交換的,但如果需要,您顯然可以交換array_merge
  • 在此示例和另一個答案中的示例中,我不確定$foo靜態屬性是否需要是public ,但我已經將它們保留為您的問題中的樣子。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM