问题
I am not sure what the title should be, but the code should explain it better:
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;
Output:
20
20 <--- Expected 21
20
21
20
21
Any idea why I got 20
instead of 21
? Even then the code below works:
$i = null ;
echo ++$i ; // output 1
I know Group
is an object that implements __toString
, i expected ++
to work with the string from __toString
or at least throw an error
回答1:
The order in which the operations happen is important:
The variable will be fetched as an object, it won't be casted to an integer (or something else).
This
++
operator increments thelval
(the long value) of thezval
, but does normally nothing else. The object pointer remains the same. The internal(fast_)increment_function
will be called with thezval
which has a pointer to the object, which checks for the type first. If it's an object, it does nothing. So when yourzval
is an object, it is as useful as a no-operation. This won't output any warning.Only then the echo instruction performs a string cast on his arguments: The
__toString
method is called and returns20
.20
will be output.
回答2:
To answer you question with a little bit of code.
$number = new Group();
echo gettype($number);
$number = "20";
echo gettype($number);
$number = 20;
echo gettype($number);
Will result in
object
string
integer
The three cases:
- You can't do any integer operation on a object, that why your code does not do what you expect. The
__toString
method will called very late, when the acutal output will computed, after you unsuccessfully tried to do an math operation with it. - You can to math with strings, because PHP internally converts them back to numbers
- Obviously you can do math with integer
Bonus:
This will work:
$number = new Group();
echo 1 + "$number"; // 21
It converts you object into a string, which could be converted into a number for a math operation.
回答3:
I think it might be clearer with just changing the names of the variables like this :
class Group {
private $number = 20;
public function __toString() {
return "$this->number";
}
}
$group = new Group();
echo $group;//print 20 as per your __toString function
++ $group;
Now it seems obvious : what is supposed to do a '++' operator on a object of type group ??
回答4:
Why don't you just:
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
I use something like this to format offsets in tables.
回答5:
This is actually more feasible than you may think -- just need to do a little bit more type casting, as follows:
<?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;
You don't have to use the string cast of course in the magic __toString() but I personally prefer to read the code that way rather than seeing the quotes -- but I think that's just a stylistic preference.
Casting the newly created object as a string causes the magic __toString method to automatically execute and it returns a numeric string which when cast to an int allows you to display the number, increment it and display it again.
Incidentally, the space between ++ and $number is okay; I closed it up b/c that is what I'm used to in other languages like C.
来源:https://stackoverflow.com/questions/16375331/increment-on-tostring