The true oo of PHP4

Source: Internet
Author: User
Tags foreach array object constructor copy reference return version
The author of this article, Johan Persson, is the developer of the famous Jpgraph Chart class library in PHP. This paper is the summary of several small problems that the author should pay attention to in the process of object-oriented development in PHP4.
Translation: Binzy Wu [mail:binzy at justdn Dot COM], limited in level, welcome to explore. 2004-2-4

Brief introduction
The object of this article is a friend (like myself) who used to develop with more mature oo [1] languages, such as Eiffel, Java, C # [2] or C + + (). There are many semantics when using PHP4 for full OO development [3] (semantic)
The traps on [4].

The content of this article can help people avoid the mistakes I have made.

Reference VS Copy Semantics
This is basically the main source of the error (at least for me). Even in PHP documents you can read PHP4 more using copy semantics (like other object-oriented languages I know), but it still makes you end up in some tiny little bit of trouble.

The next two sections are used to illustrate two small examples in which copying semantics may surprise you in two examples.

Always keep in mind that it is important that a variable of a class is not a pointer to a class but rather the actual class itself [5]. Most problems raise the misconception that an assignment operator (=) is an alias to an object, but is actually a new copy. For example, suppose $myobj is an instance of a class, and it has a set () method. The following code may not work as expected by a C + + (or Java) programmer.

function SomeFunction ($AOBJ) {$AOBJ->set (10);}
...
SomeFunction ($MYOBJ);
...


Now, it is easy to assume that the set () method invoked by the function will act on the $myobj. But it's wrong!

What actually happens is that $myobj is copied as a new copy----parameter $aobj like the original object. Then when the set () method is invoked, it only acts on the local copy rather than the original parameter----$MYOBJ.

All of these problems occur in places where direct or indirect (as above) assignment operations are involved.

For a function to act as you would expect, you have to tell PHP to use a reference to pass the object by modifying the method statement, such as:
Function SomeFunction (& $AOBJ)


If you try the above code again, you will see that the set () method will work on the original argument, because now we create a $myobj alias----$aObj in the action.

But you have to be careful, because even the and operator can not save you at any time, as the following example.

To get a reference from a reference

Suppose you have the following code:
$myObject = new SomeClass (); $myRefToObject = & $myObject;


If we want a copy of the reference now (for some reason), then what are we going to do? You may be tempted to write because $myreftoobject is already a reference:
$myCopyRefToObject = $myRefToObject;

Is that right? No! PHP creates a new copy of the object referenced by $myreftoobject. If you want to copy a reference to an object, you have to write this:
$myCopyRefToObject = & $myRefToObject;


In the case of C + +, which is equivalent to the previous example, a reference is created. Different than in PHP. This is the intuitive assumption that an experienced C + + programmer often makes, and this is the source of a small bug in your PHP program.

Please be careful of the indirect (transitive parameters) or direct problems arising therefrom.

My personal conclusion is that the best way to avoid these semantic traps is to always use references to pass objects or object assignments. This not only improves the speed of running (fewer copies of data), but also makes semantics more predictable for older dogs like me.

Using references to $this in constructors

Initializing objects as other object-seekers (Observer[6]) in the constructor of an object is a common pattern. The following lines of code are an example:
Class Bettery
{
function Bettery () {...};
function Addobserver ($method, & $obj)
{
$this->obs[] = Array ($obj, & $method)
}
function Notify () {...}
}
Class Display
{
Function Display (& $batt)
{
$batt->addobserver ("Batterynotify", $this);
}
function batterynotify () {...}
}


However, this does not work correctly if you are so instantiated objects:
$myBattery = new Battery (); $myDisplay = new Display ($myBattery);


The wrong thing to do is to use $this in the constructor when new does not return the same object. Instead, a copy of the most recently created object is returned. That is, when the Addobserver () is invoked, the object being passed is not the same as the original object. Then when the battery class tries to notify all its observers (Observer) (by invoking their Notify method), it does not invoke the display class we create but the class that $this represents (that is, the copy of the display class that we created). So if the Notify () method updates Some instance variables, it's not as if the original display class we're thinking of is going to be updated because the update is actually a copy. In order for it to work, you must return the constructor to the same object, as the original $this symbolizes. It can be constructed by adding & symbols to display, such as $mydisplay = & new Display ($myBattery);
A direct result is that the client of any display class must understand the implementation details of display. In fact, this raises a potentially contentious issue: the construction of all objects must use additional & symbols. As I said, it's basically safe, but ignoring it may at some point get unwanted effects like the example above.

Another method was used in the jpgraph to solve the problem. That is, you need to "new" an object using the so-called two-phase construct by adding a safe use of the "Init ()" Method of the & $this reference (simply because the $this reference in the constructor returns a copy of the object rather than is expected to do). So the example above will be implemented as follows:
$myBattery = new Battery ();
$myDisplay = new Display ();
$myDisplay->init ($myBattery);


such as the "Linearscale" class in jpgraph.php.


Using foreach

Another problem with the different results of a similar code is the "foreach" structure. Examine the following two different versions of the loop structure.
Version 1
foreach ($this->plots as $p)
{
$p->update ();
}
...


Version 2
for ($i =0; $i <count ($this->plots); + + $i)
{
$this->plots[$i]->update ();
}


Now is a question worth 10 dollars [7]: Version1==version2?

The surprising answer is: no! This is a small but crucial difference. In version 1, the Update () method will be used as a copy of the object in the "plots[]" array. Therefore, the original object in the array is not updated.

The update () method in version 2 will act as expected on an object in the "plots[]" array.

As stated in the first section, this is the result of PHP handling object instances as objects themselves rather than as object references.

Nasa
[1]. oo:object-oriented, object oriented.
[2]. There is no C # in the original, all because of Binzy's personal hobby.
[3]. Semantic is translated as "semantic" in this article, please contact Binzy if you have any suggestions.
[4]. There is a famous "C + + Gotchas" in C + +.
[5]. The class here should refer to the instance, which is the instance.
[6]. See "[GoF95]", or "design Patterns".
[7]. There's a very interesting little story about the deal:
Someone bought a horse for 60 dollars and sold it for 70 dollars, then he bought it back with 80 dollars and sold it for 90 dollars. In this horse deal, he? (a) a loss of USD 10; (B) balance of payments; © made 10 dollars; (D) earned 20 dollars; (E) earned 30 of dollars.
This is a simple math question calculated by the University of Michigan psychologist Mel and Burke's students. As a result, fewer than 40% of college students were able to make the right answer, and most thought they earned only 10 dollars. In fact, the condition of the problem is very clear, this is two transactions, each time to earn 10 dollars, And a lot of people mistakenly think that when he bought it back with 80 dollars, he lost 10 dollars. Interestingly, the same question was presented in a different way: one man bought a white horse for 60 dollars, it was sold at a value of $70 and then sold for 80 dollars for a dark horse and 90 dollars. In the trading of the horse, he ____ (the same five choices are listed). Another group of college students answered the question, and the results were all correct.



Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.