PHP4 is really OO. JohanPersson, creator of PHP4's true OO text, is a developer of the famous JpGraph chart class library in PHP. this article is the true OO of the total number of small issues that the author should pay attention to when conducting object-oriented development in PHP4.
Author Johan Persson is the developer of the famous JpGraph chart class library in PHP. This article is a summary of several small issues that need to be paid attention to during object-oriented development in PHP4.
Translation: Binzy Wu [Mail: Binzy at JustDN dot COM]. the level is limited. welcome to explore.-2-4.
Introduction
The objects in this article are those previously used more mature OO [1] languages, such as Eiffel, Java, C # [2] or C ++ (), development friends (such as myself ). there are many semantics when using PHP4 for full OO development [3] (semantic)
On the trap [4].
I hope this article will help you avoid the mistakes I made.
Reference VS copy semantics
This is basically the main source of errors (at least for me ). even if you can read in PHP documents that PHP4 uses more copy semantics than references (for example, other object-oriented languages I know ), but it will still make you suffer from some minor problems.
The next two parts are used to illustrate two small examples. in these two examples, copying semantics may surprise you.
It is important to keep in mind that a class variable is not a pointer to the class, but the actual class itself [5]. most problems lead to misunderstanding of the value assignment operator (=), that is, to give an object an alias, but in fact it is 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 a C ++ (or Java) programmer expects.
Function SomeFunction ($ aObj) {$ aObj-> Set (10 );}
...
SomeFunction ($ myObj );
...
Now, it is easy to think that the Set () method called by this function will act on $ myObj. but this is wrong!
In fact, $ myObj is copied as a new one, which is the same as the original object ---- parameter $ aObj. then, when the Set () method is called, it only acts on the local copy instead of the original parameter ---- $ myObj.
A variety of the above problems occur in places that contain direct or indirect (as shown above) assignment operations.
In order for a function to act as you expected (maybe), you have to modify the method declaration to tell PHP to use references to pass objects, such:
Function SomeFunction (& $ aObj)
If you try the above code again, you will find that the Set () method will act on the original parameter, because now we have created a $ myObj alias ---- $ aObj.
But you have to be careful, because even the & operator can not save you at any time, as shown in the following example.
Obtain a reference from a reference
Assume the following code is available:
$ MyObject = new SomeClass (); $ myRefToObject = & $ myObject;
If we want to copy a reference (for some reason), what should we do? You may try to write $ myRefToObject because it is already referenced:
$ MyCopyRefToObject = $ myRefToObject;
Correct? No! PHP will create a new copy of the object referenced by $ myRefToObject. if you want to copy an object reference, you have to write the following:
$ MyCopyRefToObject = & $ myRefToObject;
In the C ++ example that is equivalent to the preceding example, a reference is created. different from PHP. this is an intuitive assumption that experienced C ++ programmers often make is the opposite, and this will be the source of bugs in your PHP program.
Please be careful with the indirect (passing 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 assign values to objects. this not only improves the running speed (less data copies), but also makes semantics more predictable for old dogs like me.
Use reference for $ this in the constructor
Initializing an object as an object discoverer (Observer [6]) in an object constructor is a common pattern. the following code is an example:
Class Bettery
{
Function Bettery (){...};
Function AddObserver ($ method, & $ obj)
{
$ This-> obs [] = array ($ obj, & $ method)
}
Function Notify (){...}
}
Class Display
{
Function Display (& $ batt)
{
$ Batt-> AddObserver ("batteryy Y", $ this );
}
Function BatteryNotify (){...}
}
However, this does not work normally. if you instantiate an object like this:
$ MyBattery = new Battery (); $ myDisplay = new Display ($ myBattery );
The error is that $ this in the new constructor does not return the same object. instead, a copy of the recently created object is returned. that is, when AddObserver () is called, the object transmitted is not the same as the original object. then when the Battery class tries to Notify all its Observer (Observer) (by calling their Notify method, it does not call the Display class we created, but the class represented by $ this (that is, copying the Display class we created ). therefore, if the Notify () method updates some instance variables, it is not as expected that the original Display class will be updated, because the update is actually a copy. to make it work, you must make the constructor return the same object, as represented by $ this at the beginning. you can add the & symbol to the Display structure, for example, $ myDisplay = & new Display ($ myBattery );
A direct result is that any Display Client must understand the Display implementation details. in fact, this creates a question that may cause controversy: the construction of all objects must use Additional & symbols. what I said is basically safe, but ignoring it may sometimes give the desired effect as shown in the preceding example.
Another solution is used in JpGraph. that is, you need to add a "Init ()" that can be safely used & $ this reference () "The so-called two-stage constructor of the method" new "is an object (only because $ this reference in the constructor returns a copy of the object and is not executed as expected ). therefore, the above example will be implemented as follows:
$ MyBattery = new Battery ();
$ MyDisplay = new Display ();
$ MyDisplay-> Init ($ myBattery );
For example, the "LinearScale" class in JPGraph. php.
Use foreach
Another issue with similar code but different results is the issue of the "foreach" structure, which studies different versions of the two loop structures in the pipeline.
// Version 1
Foreach ($ this-> plots as $ p)
{
$ P-> Update ();
}
...
// Version 2
For ($ I = 0; $ I Plots); ++ $ I)
{
$ This-> plots [$ I]-> Update ();
}
Now it's a question worth $10 [7]: version1 = version2?
The surprising answer is: No! This is a small but key difference. in Version 1, the Update () method will act on copies of objects in the "plots []" array. Therefore, the original objects in the array will not be updated.
In Version 2, the Update () method will act as expected on the objects in the "plots []" array.
As stated in the first part, this is the result of PHP processing the object instance as the object itself rather than as the object reference.
:
[1]. OO: Object-Oriented, object-oriented.
[2]. The original article does not contain C #, because of Binzy's personal interests.
[3]. Semantic is translated as "Semantic" in this article. if you have any suggestions, contact Binzy.
[4]. C ++ has a famous "C ++ Gotchas ".
[5]. the class here should refer to Instance, that is, Instance.
[6]. for details, see [GoF95], that is, Design Patterns ".
[7]. there is an interesting little story about transactions:
Someone bought a horse for $60 and sold it for $70. Then he bought it for $80 and sold it for $90. in this horse transaction, he? (A) lost $10; (B) balance of payments;©$10; (D) $20; (E) $30.
This is a simple arithmetic question for college students to calculate by the psychologists of the University of Michigan. as a result, less than 40% of college students can make the correct answer. most people think that they only earned 10 dollars. in fact, the condition for the problem is very clear. this is two transactions, earning 10 dollars each time, but many people mistakenly think that when he bought it back with 80 dollars, he had lost 10 dollars. interestingly, the same problem was raised in another way: one person bought a white horse for $60 and sold it for $70. then, I bought a dark horse for $80 and sold it for $90. in this deal, he ____ (listing the same five choices ). at this time, when the other group of college students answered the above questions, they all answered correctly.
Johan Persson, author of Ghost, is a developer of the famous JpGraph chart class library in PHP. This article is the author's summary of several minor issues that need to be paid attention to during object-oriented development in PHP4...