Nowe ja kontra nowe statyczne

513

Konwertuję bibliotekę PHP 5.3 do pracy na PHP 5.2. Najważniejsze, co stoi mi na drodze, to użycie późnego wiązania statycznego, na przykład return new static($options);, jeśli przekonwertuję to na, return new self($options)czy otrzymam takie same wyniki?

Jaka jest różnica między new selfi new static?

Mikrofon
źródło

Odpowiedzi:

888

czy dostanę te same wyniki?

Nie całkiem. Nie znam jednak obejścia dla PHP 5.2.

Jaka jest różnica między new selfi new static?

selfodnosi się do tej samej klasy, w której newsłowo kluczowe jest faktycznie zapisane.

static, w późnych wiązaniach statycznych PHP 5.3, odnosi się do dowolnej klasy w hierarchii, w której wywołałeś metodę.

W poniższym przykładzie Bdziedziczy obie metody A. selfInwokacja jest związany A, ponieważ jest zdefiniowana w A„s realizacji pierwszego sposobu, natomiast staticjest zobowiązany do zwanej klasy (patrz również get_called_class()).

class A {
    public static function get_self() {
        return new self();
    }

    public static function get_static() {
        return new static();
    }
}

class B extends A {}

echo get_class(B::get_self());  // A
echo get_class(B::get_static()); // B
echo get_class(A::get_self()); // A
echo get_class(A::get_static()); // A
BoltClock
źródło
ma sens. Myślę, że najlepszym rozwiązaniem jest przekazanie nazwy klasy do funkcji korzystającej z późnego wiązania statycznego, a następnie zwrócenie nowego $ className ($ options);
Mike
12
Nie musisz „przekazywać” nazwy klasy, zawsze możesz to zrobić get_called_class(), co jest faktycznie takie samo jak __CLASS__, ale zgodne z LSB.
shadowhand
7
get_called_class nie istnieje w <PHP5.3. Dlatego jeśli chcesz uzyskać nazwę klasy instancji obiektu w PHP5.2 Ta funkcja nie pomaga przy próbie konwersji biblioteki z PHP 5.3 na PHP 5.2
txwikinger 21.09.11
2
Funkcja wywoływana jako self :: theFunction () zachowuje się jak „Wykonam w kontekście klasy, do której fizycznie należę”. a funkcja wywoływana jako static :: theFunction () zachowuje się jak „Wykonam w kontekście klasy, która została faktycznie wywołana przez świat zewnętrzny”. (Przy założeniu scenariusza dziedziczenia). Dzięki
Shubhranshu,
2
W mojej głowie biorę tylko to, co intuicyjne, i robię to odwrotnie. Myślisz, że w oparciu o nazewnictwo, selfzwróci się i staticzwróci coś, czego nie można zastąpić ... Ale oto jest odwrotnie. Nigdy nie przestaję być pod wrażeniem nazewnictwa, konwencji i ogólnego stylu PHP. -_-
ahnbizcad
23

Jeśli metoda tego kodu nie jest statyczna, możesz obejść ten problem w 5.2, używając get_class($this).

class A {
    public function create1() {
        $class = get_class($this);
        return new $class();
    }
    public function create2() {
        return new static();
    }
}

class B extends A {

}

$b = new B();
var_dump(get_class($b->create1()), get_class($b->create2()));

Wyniki:

string(1) "B"
string(1) "B"
Marius Balčytis
źródło
17
Jeśli metoda nie jest statyczna, późne wiązania statyczne stają się zupełnie nieistotne.
BoltClock
1
Na przykład możesz użyć go w metodzie „kopiuj”, w której obiekt jest kopiowany bez użycia clone, ale tylko przez ponowne utworzenie i ustawienie właściwości. $copy = new static(); $copy->set($this->get()); return $copy;
Marius Balčytis
9
@BoltClock Na pewno nie? Jeśli wywołujesz przesłoniętą metodę statyczną z metody instancji podklasy, wówczas wybór self::lub static::będzie mieć wpływ na to, czy używana jest wersja tej metody statycznej klasy podstawowej lub podklasy. Wobec braku jakiegoś powodu, by sądzić, że taka sytuacja z natury wskazuje na złą praktykę (i nie widzę żadnego powodu, dla którego powinna tak być), wybór pomiędzy self::i static::jest równie istotny w przypadku metod niestatycznych, jak w przypadku metody statyczne. Czy źle zrozumiałem twój komentarz, czy jest to po prostu błąd?
Mark Amery
4
@Mark Amery: Hmm, nie myślałem o tym. Masz całkowitą rację. Zakładałem, że w omawianej metodzie instancji nie będą wywoływane żadne metody statyczne, ale na podstawie twojego przykładu widzę, że byłoby to bardzo naiwne założenie.
BoltClock
Późne wiązania
DevWL
7

Oprócz odpowiedzi innych:

static :: zostanie obliczony na podstawie informacji o środowisku wykonawczym.

Oznacza to, że nie można użyć static::we właściwości klasy, ponieważ wartości właściwości:

Musi istnieć możliwość oceny podczas kompilacji i nie może zależeć od informacji w czasie wykonywania.

class Foo {
    public $name = static::class;

}

$Foo = new Foo;
echo $Foo->name; // Fatal error

Za pomocą self::

class Foo {
    public $name = self::class;

}
$Foo = new Foo;
echo $Foo->name; // Foo

Pamiętaj, że komentarz błędu krytycznego w utworzonym przeze mnie kodzie nie wskazuje, gdzie wystąpił błąd, błąd wystąpił wcześniej, zanim obiekt został utworzony jako @Grapestain wspomniany w komentarzach

Deszcz
źródło
4
Zauważ, że błąd jest zgłaszany w linii 2 public $name = static::class;, a nie w linii 7, jak sugeruje to przykład. Błąd mówi: „statyczne :: class nie może być użyte do rozpoznawania nazw klas w czasie kompilacji”, co oznacza, że ​​problemem nie jest próba uzyskania dostępu do pola $ name, ale znacznie wcześniej przy kompilacji klasy PHP. Linia 7 (lub 6) nie zostanie osiągnięta w pierwszym przykładzie.
sbnc.eu
@Grapestain Komentarz, który napisałem w tym przykładzie, miał pokazać wynik końcowy, a nie wskazać, gdzie rzeczywiście wystąpił błąd. Ale i tak dziękuję za zwrócenie na to uwagi.
Deszcz
Racja, nie chciałem krytykować, po prostu wyjaśniłem, co wprawiło mnie w zakłopotanie w nadziei, że może to pomóc innym. W każdym razie pomocny przykład!
sbnc.eu,