2013-05-04 9 views
9

Ich bin nicht sicher, was der Titel sein soll, aber der Code sollte es besser erklären:Erhöhungsschritte auf „__toString“

class Group { 
    private $number = 20; 

    public function __toString() { 
     return "$this->number"; 
    } 
} 

$number = new Group(); 
echo $number, PHP_EOL; 
echo ++ $number, PHP_EOL; 

echo PHP_EOL; 

$number = "20"; 
echo $number, PHP_EOL; 
echo ++ $number, PHP_EOL; 

echo PHP_EOL; 

$number = 20; 
echo $number, PHP_EOL; 
echo ++ $number, PHP_EOL; 

Ausgang:

20 
20    <--- Expected 21 

20 
21 

20 
21 

Jede Idee, warum ich 20 bekam statt 21? Selbst dann unterhalb der Code funktioniert:

$i = null ; 
echo ++$i ; // output 1 

Ich weiß Group ein Objekt, das __toString implementiert, erwartete ich ++ von __toString mit der Zeichenfolge zu arbeiten oder zumindest throw an error

+0

Bietet PHP eine Möglichkeit, die Inkrementoperatoren zu überladen? Da Ihre Klasse nicht einfach in einen Zahlentyp konvertiert werden kann, müssen Sie PHP wahrscheinlich mitteilen, was Sie tun wollen. – dlp

+1

Wenn Sie in der Group-Klasse $ number nicht privat deklarieren und dann versuchen, echo ++ $ number-> number, PHP_EOL; funktioniert? – LuckyStarr

+0

Nein .. aber das war inkrement auf string und auch wenn sonst .. ich sollte einen fehler bekommen – Baba

Antwort

12

Die Reihenfolge, in der die Operationen geschehen ist wichtig:

  1. Die Variable als Objekt abgerufen werden wird, wird es nicht auf eine ganze Zahl (oder etwas anderes) gegossen werden.

  2. Dieser Operator ++ inkrementiert die (der lange Wert) der zval, aber normalerweise nichts anderes. Der Objektzeiger bleibt gleich. Der interne (fast_)increment_function wird mit dem zval aufgerufen, der einen Zeiger auf das Objekt hat, der zuerst nach dem Typ sucht. Wenn es ein Objekt ist, tut es nichts. Wenn Ihr zval ein Objekt ist, ist es genauso nützlich wie eine Nicht-Operation. Dies wird keine Warnung ausgeben.

  3. Nur dann führt der Echo-Befehl eine Zeichenfolge für seine Argumente aus: Die Methode __toString wird aufgerufen und gibt 20 zurück.

  4. 20 wird ausgegeben.

9

zu beantworten, die Sie mit ein wenig in Frage von Code.

$number = new Group(); 
echo gettype($number); 

$number = "20"; 
echo gettype($number); 

$number = 20; 
echo gettype($number); 

Wird in

object 
string 
integer 

Die drei Fälle ergeben:

  • Sie können nicht tun, um jede Integer-Operation auf einem Objekt, das, warum Ihr Code nicht tut, was Sie erwarten. Die __toString Methode wird sehr spät aufgerufen, wenn die acutal Ausgabe berechnet wird, nachdem Sie erfolglos versucht haben, eine mathematische Operation damit auszuführen.
  • Sie können Strings in Mathe mit, weil PHP intern sie zu Zahlen konvertiert zurück
  • Natürlich können Sie tun Mathe mit integer

Bonus:

Dies funktioniert:

$number = new Group(); 
echo 1 + "$number"; // 21 

Es konvertiert Ihr Objekt in eine Zeichenfolge, die in eine Zahl für eine mathematische Operation umgewandelt werden könnte.

+0

Das Hinzufügen von explizit eins zum Variablenausdruck öffnet tatsächlich die Möglichkeit, die hinzugefügte Menge sehr einfach zu ändern. Pre- oder Post-Inkrement-Operationen sollten vermieden werden. Du wirst nie wirklich wissen, was passieren wird. [Douglas Crockford mag sie nicht.] (Http://stackoverflow.com/questions/971312/why-avoid-increment-and-decrement-operators-in-javascript) - und in PHP ist es viel einfacher zu nutzen die kurze Version '$ i + = 1 ^' anstelle von '$ i ++' - nur ein weiteres Zeichen. Und versuche, um 2 zu erhöhen ... :) – Sven

2

ich denke, es könnte klarer sein mit nur die Namen der Variablen wie folgt zu ändern:

class Group { 
    private $number = 20; 

    public function __toString() { 
     return "$this->number"; 
    } 
} 

$group = new Group(); 
echo $group;//print 20 as per your __toString function 

++ $group; 

Nun scheint es offensichtlich: was sollte einen ‚++‘ Betreiber auf einem Objekt vom Typ Gruppe tun ??

1

Warum gehst du nicht einfach:

class Group { 
    private $number = 0; 
    public function __construct($number = 0){ 
     $this->number = intval($number); 
    } 
    public function __toString() { 
     return number_format(++$this->number); // pre-increment 
    } 
} 
$g = new Group(); 
echo $g; // 1 
echo $g; // 2 

ich so etwas wie dieses verwenden, um Formatkorrekturen in Tabellen.

0

Dies ist eigentlich mehr möglich, als Sie vielleicht denken - müssen nur ein wenig mehr Art Casting tun, wie folgt:

<?php 

class Group { 
private $number = 20; 

    public function __toString() { 
     return (string) $this->number; // replace "" w/string cast 
    } 
} 

$number = (int)(string) new Group(); 
echo $number, PHP_EOL; 
echo ++$number, PHP_EOL; 

Sie müssen die String-Umwandlung von nicht verwenden natürlich in der magischen __toString(), aber ich persönlich bevorzuge es, den Code auf diese Weise zu lesen, anstatt die Zitate zu sehen - aber ich denke, das ist nur eine stilistische Präferenz.

Wenn das neu erstellte Objekt als Zeichenfolge übergeben wird, wird die magische __toString-Methode automatisch ausgeführt und eine numerische Zeichenfolge zurückgegeben. Wenn sie in einen Int umgewandelt wird, können Sie die Zahl anzeigen, inkrementieren und erneut anzeigen.

Übrigens ist der Abstand zwischen ++ und $ Nummer in Ordnung; Ich habe es geschlossen b/c, das ist, was ich in anderen Sprachen wie C. gewohnt bin.