2012-12-08 19 views
10

Mam klasy bazowej, które muszę wywoływać funkcje na klasie, która jest przywoływana w klasie potomnej.Uzyskaj statyczne zmienne klasy potomnej z klasy nadrzędnej?

dość łatwe,

class base_class { 

    public function doSomethingWithReference(){ 
     $this->reference->doSomething(); 
    } 
} 

class extended_class extends base_class{ 

    protected $reference; 

    public function __construct($ref){ 
     $this->reference = $ref; 
    } 
} 

Teraz to działa prawidłowo oczywiście

Ale kiedy jestem debugowania Nie dbam o wartości $this->reference

ale obiekt, który $this->reference odnosi się do jest ogromny!

, więc gdy wykonam print_r($instanceOfExtendedClass), otrzymam wydruk tego obiektu.

Odwołanie jest teraz różne dla każdej klasy, która rozszerza się o base_class.

To, co chciałem zrobić, to ustawić jako reference statyczną właściwość klasy extended_class.

Ale zmiana doSomethingWithReference na self::$reference powoduje zgłoszenie niezdefiniowanego błędu zmiennej.

I odwrotnie ustawienie zmiennej statycznej w base_class i modyfikowanie jej z extended_class nie działa, ponieważ zmienia zmienną dla wszystkiego, co rozciąga się od tej klasy.

Czy jest jakiś sposób, aby to zrobić, aby uzyskać wydruk z $this->reference?

+2

Z jaką wersją PHP pracujesz? Było kilka [* dużych * zmian w "statycznym" zachowaniu w 5.3] (http://php.net/language.oop5.late-static-bindings), a wiedza, czy utkniesz na czymś starszym, da ci bardzo odmienna odpowiedź. – Charles

+1

Wersja PHP 5.3 – Hailwood

+0

Ta struktura klasowa narusza coś, po prostu nie jestem pewna co to jest :) –

Odpowiedz

14

Ponieważ używasz PHP 5.3, można użyć late static binding rozwiązać statyczne wezwanie do właściwej klasy w czasie wykonywania.

class base_class { 

    public function doSomethingWithReference(){ 
     static::$reference->doSomething(); 
    } 

} 

class extended_class extends base_class{ 

    protected static $reference; 

    public function __construct($ref){ 
     static::$reference = $ref; 
    } 

} 

Big fat przypomnienia: To jeden extended_class::$reference będzie dzielona między wszystko z extended_class przypadkach. Jeśli to nie jest to, co zamierzacie, to nie zadziała.

Wygląda na to, że martwisz się pamięcią lub wykorzystaniem zasobów. W PHP wszystkie obiekty są przekazywane przez odniesienie. Oznacza to, że przekazywanie obiektu jako argumentu lub tworzenie jego kopii itp. Nie wymaga dodatkowej pamięci. Jeśli chcesz odwołać się do obiektu w wielu innych obiektach, spowoduje to zużycie dodatkowej pamięci.


Gdybym miał extended_class i inną identyczną klasę (słownie extended_class1) będą dzielić odniesienia, jak również? czy wszystkie instancje extended_class miałyby jedno odniesienie, a wszystkie instancje extended_class1 "współużytkowałyby inne (przypadek idealny)?

Wygląda na to, że udostępnianie jest oparte na miejscu zdefiniowania zmiennej statycznej.Dwa przykłady, zarówno z interaktywnego pytania w języku PHP:

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } } 
php > class Base { protected static $ref; public function foo() { echo static::$ref->me, "\n"; } } 
php > class Inherit_1 extends Base { public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_2 extends Base { public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_3 extends Inherit_1 {} 
php > $shared_1 = new Shared(1) 
php > ; 
php > $shared_2 = new Shared(2); 
php > $shared_3 = new Shared(3); 
php > 
php > $in_1 = new Inherit_1($shared_1); 
php > $in_2 = new Inherit_2($shared_2); 
php > $in_3 = new Inherit_3($shared_3); 
php > 
php > $in_1->foo(); 
3 
php > $in_2->foo(); 
3 
php > $in_3->foo(); 
3 

W tym przypadku, ponieważ odniesienie żyje w klasie bazowej, każdy widzi ten sam. Przypuszczam, że to ma jakiś sens.

Co stanie się, gdy zadeklarujemy odniesienie do każdej klasy dziecka .. przez większość czasu?

php > class Shared { public $me; public function __construct($me) { $this->me = $me; } } 
php > class Base { public function foo() { echo static::$ref->me, "\n"; } } 
php > class Inherit_1 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_2 extends Base { protected static $ref; public function __construct($ref) { static::$ref = $ref; } } 
php > class Inherit_3 extends Inherit_1 {} 
php > class Inherit_4 extends Inherit_1 { protected static $ref; } 
php > $shared_1 = new Shared(1); 
php > $shared_2 = new Shared(2); 
php > $shared_3 = new Shared(3); 
php > $shared_4 = new Shared(4); 
php > $in_1 = new Inherit_1($shared_1); 
php > $in_2 = new Inherit_2($shared_2); 
php > $in_3 = new Inherit_3($shared_3); 
php > $in_4 = new Inherit_4($shared_4); 
php > $in_1->foo(); 
3 
php > $in_2->foo(); 
2 
php > $in_3->foo(); 
3 
php > $in_4->foo(); 
4 

Ponieważ 3 odziedziczył od 1 bez deklarowania własnej właściwości statycznej, odziedziczył 1. Kiedy ustawiamy 3 na Shared (3), to nadpisujemy 1 istniejący Shared (1).

Wniosek: Aby to zadziałało, właściwość musi być zadeklarowana jako co klasa, która potrzebuje pojedynczego unikalnego odwołania. Pamiętaj, że ten kod jest ważny od wersji 5.4.x.

+0

Właściwie nie martwię się pamięcią, to po prostu debugowanie, nie lubię konieczności przewijania ~ 600 linii (obiektów Code Igniter!), Aby zobaczyć, jakie są właściwości obiektów! Twój punkt dotyczący 'extended_class :: $ reference' współużytkowania odniesień, Gdybym miał' extended_class' i inną identyczną klasę (powiedzmy 'extended_class1'), czy też udostępniliby to odniesienie? czy wszystkie instancje 'extended_class' 'miałyby jedno odniesienie, podczas gdy wszystkie instancje' extended_class1'' współdzieliłyby inne (przypadek idealny)? – Hailwood

+0

@Hailwood, zaktualizowałem swoją odpowiedź testem demonstrującym lokalizację właściwości statycznej. – Charles

2

stanowić sposób dla rodzica, aby uzyskać dostęp do statycznego elementu dziecka:

<?php 

abstract class base_class { 
    abstract protected function reference(); 
    // If you want to be able to instanciate base class directly, use the following 2 lines in place of the previous 2 lines: 
//class base_class { 
    //protected function reference() {} 

    public function doSomethingWithReference(){ 
     $this->reference()->doSomething(); 
    } 
} 

class extended_class extends base_class{ 
    protected static $reference; 

    public function __construct($ref){ 
     self::$reference = $ref; 
    } 

    protected function reference(){ 
     return self::$reference; 
    } 
} 

class ref { 
    public function doSomething(){ 
     echo __METHOD__; 
    } 
} 

$ref = new ref(); 
$ec = new extended_class($ref); 
$ec->doSomethingWithReference(); 

print_r($ec); 
?> 
+2

-1, to tylko zrzut kodu. Nie wyjaśniłeś, czym jest ten kod, dlaczego działa, jak działa i jak odpowiada na pytanie. – Charles

+2

Dzięki za krytykę @Charles - nie ma sarkazmu. Tak naprawdę, dawaj +1 do Twojego komentarza. W przyszłości z pewnością będę bardziej gadatliwy i nie zakładam, że czytelnik zrozumie, co się dzieje, po prostu czytając kod. Nie mam przy sobie pudełka z PHP <5.3, ale sądzę, że ten przykład zadziała dla tych, którzy utknęli bez późnych wiązań statycznych. Gdy potwierdzę, że działa w mniejszych wersjach, zaktualizuję moją odpowiedź, aby wyjaśnić, dlaczego i jakie hows, i stwierdzam, że ta odpowiedź ma wartość dla użytkowników PHP <5.3. –

Powiązane problemy