- GUI
- Windows API tutorial
- Introduction to Windows API
- Windows API main functions
- System functions in Windows API
- Strings in Windows API
- Date & time in Windows API
- A window in Windows API
- First steps in UI
- Windows API menus
- Windows API dialogs
- Windows API controls I
- Windows API controls II
- Windows API controls III
- Advanced controls in Windows API
- Custom controls in Windows API
- The GDI in Windows API
- PyQt4 tutorial
- PyQt5 tutorial
- Qt4 tutorial
- Introduction to Qt4 toolkit
- Qt4 utility classes
- Strings in Qt4
- Date and time in Qt4
- Working with files and directories in Qt4
- First programs in Qt4
- Menus and toolbars in Qt4
- Layout management in Qt4
- Events and signals in Qt4
- Qt4 Widgets
- Qt4 Widgets II
- Painting in Qt4
- Custom widget in Qt4
- The Breakout game in Qt4
- Qt5 tutorial
- Introduction to Qt5 toolkit
- Strings in Qt5
- Date and time in Qt5
- Containers in Qt5
- Working with files and directories in Qt5
- First programs in Qt5
- Menus and toolbars in Qt5
- Layout management in Qt5
- Events and signals in Qt5
- Qt5 Widgets
- Qt5 Widgets II
- Painting in Qt5
- Custom widget in Qt5
- Snake in Qt5
- The Breakout game in Qt5
- PySide tutorial
- Tkinter tutorial
- Tcl/Tk tutorial
- Qt Quick tutorial
- Java Swing tutorial
- JavaFX tutorial
- Java SWT tutorial
- wxWidgets tutorial
- Introduction to wxWidgets
- wxWidgets helper classes
- First programs in wxWidgets
- Menus and toolbars in wxWidgets
- Layout management in wxWidgets
- Events in wxWidgets
- Dialogs in wxWidgets
- wxWidgets widgets
- wxWidgets widgets II
- Drag and Drop in wxWidgets
- Device Contexts in wxWidgets
- Custom widgets in wxWidgets
- The Tetris game in wxWidgets
- wxPython tutorial
- Introduction to wxPython
- First Steps
- Menus and toolbars
- Layout management in wxPython
- Events in wxPython
- wxPython dialogs
- Widgets
- Advanced widgets in wxPython
- Drag and drop in wxPython
- Internationalisation
- Application skeletons in wxPython
- The GDI
- Mapping modes
- Creating custom widgets
- Tips and Tricks
- wxPython Gripts
- The Tetris game in wxPython
- C# Winforms Mono tutorial
- Java Gnome tutorial
- Introduction to Java Gnome
- First steps in Java Gnome
- Layout management in Java Gnome
- Layout management II in Java Gnome
- Menus in Java Gnome
- Toolbars in Java Gnome
- Events in Java Gnome
- Widgets in Java Gnome
- Widgets II in Java Gnome
- Advanced widgets in Java Gnome
- Dialogs in Java Gnome
- Pango in Java Gnome
- Drawing with Cairo in Java Gnome
- Drawing with Cairo II
- Nibbles in Java Gnome
- QtJambi tutorial
- GTK+ tutorial
- Ruby GTK tutorial
- GTK# tutorial
- Visual Basic GTK# tutorial
- PyGTK tutorial
- Introduction to PyGTK
- First steps in PyGTK
- Layout management in PyGTK
- Menus in PyGTK
- Toolbars in PyGTK
- Signals & events in PyGTK
- Widgets in PyGTK
- Widgets II in PyGTK
- Advanced widgets in PyGTK
- Dialogs in PyGTK
- Pango
- Pango II
- Drawing with Cairo in PyGTK
- Drawing with Cairo II
- Snake game in PyGTK
- Custom widget in PyGTK
- PHP GTK tutorial
- C# Qyoto tutorial
- Ruby Qt tutorial
- Visual Basic Qyoto tutorial
- Mono IronPython Winforms tutorial
- Introduction
- First steps in IronPython Mono Winforms
- Layout management
- Menus and toolbars
- Basic Controls in Mono Winforms
- Basic Controls II in Mono Winforms
- Advanced Controls in Mono Winforms
- Dialogs
- Drag & drop in Mono Winforms
- Painting
- Painting II in IronPython Mono Winforms
- Snake in IronPython Mono Winforms
- The Tetris game in IronPython Mono Winforms
- FreeBASIC GTK tutorial
- Jython Swing tutorial
- JRuby Swing tutorial
- Visual Basic Winforms tutorial
- JavaScript GTK tutorial
- Ruby HTTPClient tutorial
- Ruby Faraday tutorial
- Ruby Net::HTTP tutorial
- Java 2D games tutorial
- Java 2D tutorial
- Cairo graphics tutorial
- PyCairo tutorial
- HTML5 canvas tutorial
- Python tutorial
- Python language
- Interactive Python
- Python lexical structure
- Python data types
- Strings in Python
- Python lists
- Python dictionaries
- Python operators
- Keywords in Python
- Functions in Python
- Files in Python
- Object-oriented programming in Python
- Modules
- Packages in Python
- Exceptions in Python
- Iterators and Generators
- Introspection in Python
- Ruby tutorial
- PHP tutorial
- Visual Basic tutorial
- Visual Basic
- Visual Basic lexical structure
- Basics
- Visual Basic data types
- Strings in Visual Basic
- Operators
- Flow control
- Visual Basic arrays
- Procedures & functions in Visual Basic
- Organizing code in Visual Basic
- Object-oriented programming
- Object-oriented programming II in Visual Basic
- Collections in Visual Basic
- Input & output
- Tcl tutorial
- C# tutorial
- Java tutorial
- AWK tutorial
- Jetty tutorial
- Tomcat Derby tutorial
- Jtwig tutorial
- Android tutorial
- Introduction to Android development
- First Android application
- Android Button widgets
- Android Intents
- Layout management in Android
- Android Spinner widget
- SeekBar widget
- Android ProgressBar widget
- Android ListView widget
- Android Pickers
- Android menus
- Dialogs
- Drawing in Android
- Java EE 5 tutorials
- Introduction
- Installing Java
- Installing NetBeans 6
- Java Application Servers
- Resin CGIServlet
- JavaServer Pages, (JSPs)
- Implicit objects in JSPs
- Shopping cart
- JSP & MySQL Database
- Java Servlets
- Sending email in a Servlet
- Creating a captcha in a Servlet
- DataSource & DriverManager
- Java Beans
- Custom JSP tags
- Object relational mapping with iBATIS
- Jsoup tutorial
- MySQL tutorial
- MySQL quick tutorial
- MySQL storage engines
- MySQL data types
- Creating, altering and dropping tables in MySQL
- MySQL expressions
- Inserting, updating, and deleting data in MySQL
- The SELECT statement in MySQL
- MySQL subqueries
- MySQL constraints
- Exporting and importing data in MySQL
- Joining tables in MySQL
- MySQL functions
- Views in MySQL
- Transactions in MySQL
- MySQL stored routines
- MySQL Python tutorial
- MySQL Perl tutorial
- MySQL C API programming tutorial
- MySQL Visual Basic tutorial
- MySQL PHP tutorial
- MySQL Java tutorial
- MySQL Ruby tutorial
- MySQL C# tutorial
- SQLite tutorial
- SQLite C tutorial
- SQLite PHP tutorial
- SQLite Python tutorial
- SQLite Perl tutorial
- SQLite Ruby tutorial
- SQLite C# tutorial
- SQLite Visual Basic tutorial
- PostgreSQL C tutorial
- PostgreSQL Python tutorial
- PostgreSQL Ruby tutorial
- PostgreSQL PHP tutorial
- PostgreSQL Java tutorial
- Apache Derby tutorial
- SQLAlchemy tutorial
- MongoDB PHP tutorial
- MongoDB Java tutorial
- MongoDB JavaScript tutorial
- MongoDB Ruby tutorial
- Spring JdbcTemplate tutorial
- JDBI tutorial
Object-oriented programming II in PHP
In this chapter of the PHP tutorial, we continue describing OOP in PHP.
The static keyword
We can declare class properties and methods to be static
. The static
properties and methods do not belong to the instance of the class. They belong to the class itself. They are accessible through the scope resolution operator ::
.
staticmethod.php
<?php class Sys { public static function println($string) { echo "$string\n"; } } Sys::println("PHP"); Sys::println("PERL"); Sys::println("Python"); Sys::println("Pike"); ?>
In the above PHP script, we have a static println()
method. It prints a string and starts a new line. This example is inspired by the Java language.
Sys::println("PHP");
We do not need an object to call println()
method. We call static
methods by specifying the class name, followed by double colon operator and the method name.
$ php static1.php PHP PERL Python Pike
This is the output of the script.
staticvariable.php
<?php class Math { public static $PI = 3.14159265359; } echo Math::$PI . "\n"; ?>
And now we have an example with a static
variable.
echo Math::$PI . "\n";
We access the variable by specifying the class name, followed by the scope resolution operator and the variable name.
The final keyword
Final methods cannot be overridden and final classes cannot be extended. The final
keyword is a matter of design of the application. Some classes should not be extended and some methods should not be overridden. This behaviour is enforced by the final
keyword.
finalmethod.php
<?php class Base { final function say() { echo "Base class"; } } class Derived extends Base { function say() { echo "Derived class"; } } ?>
This PHP script won't compile. We get an error "Cannot override final method Base::say()".
finalclass.php
<?php final class Math { static function getPI() { return 3.141592; } } class DerivedMath extends Math { function say() { echo "DerivedMath class"; } } ?>
In the previous PHP script, we have a prototype base Math
class. The sole purpose of this class is to provide some helpful methods and constants to the programmer. (In our case we have only one method for simplicity reasons.) It is not created to be extended. To prevent uninformed other programmers to derive from this class, the creators made the class final
. If you try to run this PHP script, you get the following error: "Fatal error: Class DerivedMath may not inherit from final class (Math)".
Deep copy vs shallow copy
Copying of data is an important task in programming. Object is a composite data type in OOP. Member field in an object may be stored by value or by reference. Copying may be performed in two ways.
A shallow copy copies all values and references into a new instance. The data to which a reference is pointing is not copied; only the pointer is copied. The new references are pointing to the original objects. Any changes to the reference members affect both objects.
A deep copy copies all values into a new instance. In case of members that are stored as references a deep copy performs a deep copy of data that is being referenced. A new copy of a referenced object is created, and the pointer to the newly created object is stored. Any changes to those referenced objects will not affect other copies of the object. Deep copies are fully replicated objects.
In PHP, we have a copy
keyword which performs a shallow copy by default. It calls the object's __clone()
method. We can implement the method to create our custom deep copy. In PHP all objects are assigned by reference.
The next two examples perform a shallow and a deep copy on objects.
shallowcopy.php
<?php class Object { public $id; public $size; public $color; function __construct($id, $size, $color) { $this->id = $id; $this->size = $size; $this->color = $color; } } class Color { public $red; public $green; public $blue; function __construct($red, $green, $blue) { $this->red = $red; $this->green = $green; $this->blue = $blue; } } $color = new Color(23, 42, 223); $object1 = new Object(23, "small", $color); $object2 = clone $object1; $object2->id++; $object2->color->red = 255; $object2->size = "big"; print_r($object1); print_r($object2); ?>
In the above PHP script, we define two custom objects: Object
and Color
. The Object
object will have a reference to the Color
object.
$color = new Color(23, 42, 223);
We create an instance of the Color object.
$object1 = new Object(23, "small", $color);
An instance of the Object object is created. It passes the instance of the Color object to its constructor.
$object2 = clone $object1;
We perform a shallow copy of the Object
object.
$object2->id++; $object2->color->red = 255; $object2->size = "big";
Here we modify the member fields of the cloned object. We increment the id, change the red part of the color object, and change the size to "big".
print_r($object1); print_r($object2);
We use the print_r()
function to compare the results.
$ php shallowcopy.php Object Object ( [id] => 23 [size] => small [color] => Color Object ( [red] => 255 [green] => 42 [blue] => 223 ) ) Object Object ( [id] => 24 [size] => big [color] => Color Object ( [red] => 255 [green] => 42 [blue] => 223 ) )
We can see that the ids are different: 23 vs 24. The size is different: "small" vs "big". But the red part of the color object is same for both instances: 255. Changing member values of the cloned object did not affect the original object. Changing members of the referenced object has affected the original object too. In other words, both objects refer to the same color object in memory.
To change this behaviour, we will do a deep copy next.
deepcopy.php
<?php class Object { public $id; public $size; public $color; function __construct($id, $size, $color) { $this->id = $id; $this->size = $size; $this->color = $color; } function __clone() { $red = $this->color->red; $green = $this->color->green; $blue = $this->color->blue; $this->color = new Color($red, $green, $blue); } } class Color { public $red; public $green; public $blue; function __construct($red, $green, $blue) { $this->red = $red; $this->green = $green; $this->blue = $blue; } } $color = new Color(23, 42, 223); $object1 = new Object(23, "small", $color); $object2 = clone $object1; $object2->id++; $object2->color->red = 255; $object2->size = "big"; print_r($object1); print_r($object2); ?>
In this PHP script, we have implemented the __clone()
method.
function __clone() { $red = $this->color->red; $green = $this->color->green; $blue = $this->color->blue; $this->color = new Color($red, $green, $blue); }
Inside the __clone()
method, we copy the red, green, and blue member fields and create a new Color object. Now, the $color
field points to a different Color
object.
$ php deepcopy.php Object Object ( [id] => 23 [size] => small [color] => Color Object ( [red] => 23 [green] => 42 [blue] => 223 ) ) Object Object ( [id] => 24 [size] => big [color] => Color Object ( [red] => 255 [green] => 42 [blue] => 223 ) )
Now the red part of the referenced Color
object is not the same. The original object has retained its previous 23 value.
Exceptions
Exceptions are designed to handle the occurrence of exceptions, special conditions that change the normal flow of program execution. Exceptions are raised or thrown and initiated.
During the execution of our application, many things might go wrong. A disk might get full and we cannot save our file. An Internet connection might go down and our application tries to connect to a site. All these might result in a crash of our application. To prevent happening this, we must cope with all possible errors that might occur. For this, we can use the exception handling.
Exceptions are available since PHP 5. Most PHP errors still use the old error reporting and not exceptions. With a set_error_handler()
we can do a workaround for this.
zerodiv.php
<?php set_error_handler("error_handler"); function error_handler($errno, $errstring, $errfile, $line, $trace) { throw new ErrorException($errstring, $errno, 0, $errfile, $line); } try { $a = 0; $b = 32; $c = $b / $a; } catch(ErrorException $e) { echo "Error occurred\n"; echo $e->getMessage(), "\n"; } ?>
In the above PHP script, we intentionally divide a number by zero. This leads to an error. The error is not an exception and is not caught by the catch
keyword.
set_error_handler("error_handler");
The set_error_handler()
function sets a user defined error handler function.
function error_handler($errno, $errstring, $errfile, $line, $trace) { throw new ErrorException($errstring, $errno, 0, $errfile, $line); }
Inside the set_error_handler()
function, we throw an ErrorException
. This exception is later caught by the catch
keyword.
try { $a = 0; $b = 32; $c = $b / $a; }
The code that we are checking against an error is put inside the block following the try
keyword.
} catch(Exception $e) { echo $e->getMessage(); }
The catch
keyword is used to catch an exception. To find out more info, we call the getMessage()
method on the exception object.
$ php zerodiv.php Error occurred Division by zero
This is the output of our PHP script.
The Exception
is a base class for all exceptions. We can create our own exceptions derived from this base class.
myexception.php
<?php define("LIMIT", 333); class BigValueException extends Exception { public function __construct($message) { parent::__construct($message); } } $a = 34325; try { if ($a > LIMIT) { throw new BigValueException("Exceeded the maximum value allowed\n"); } } catch (BigValueException $e) { echo $e->getMessage(); } ?>
Let's say, we have a situation in which we cannot deal with big numbers.
define("LIMIT", 333);
Numbers bigger than this constant are considered to be "big" by our PHP script.
class BigValueException extends Exception {
We have a BigValueException
class. This class derives from the Exception
class through the extends
keyword.
public function __construct($message) { parent::__construct($message); }
Inside the constructor, we call the parent's constructor.
if ($a > LIMIT) { throw new BigValueException("Exceeded the maximum value allowed\n"); }
If the value is bigger than the limit, we throw our custom exception. We give the exception a message "Exceeded the maximum value allowed".
} catch (BigValueException $e) { echo $e->getMessage(); }
We catch the exception and print its message to the console.
Constructor overloading
PHP does not support diret constructor overloading. In other words, each class can only have one constructor defined. Many programmers that already know Java or C# languages are looking for a similar feature in PHP. There are two ways how we can handle this.
The first solution is based on the func_get_args()
function. The second solution uses a factory pattern.
constructors.php
<?php class Book { private $author = "not specified"; private $title = "not specified"; private $year = "not specified"; public function __construct() { $args = func_get_args(); foreach(["title", "author", "year"] as $item) { if(empty($args)) { break; } $this->$item = array_shift($args); } } public function __toString() { return "Author: $this->author\nTitle: $this->title\nPublished: $this->year\n\n"; } } $book1 = new Book("Stephen Prata", "C Primer Plus"); echo $book1; $book2 = new Book("Joshua Bloch", "Effective Java", 2008); echo $book2; ?>
In the above script, we have a Book
class. We instantiate the class with 2 and 3 parameters.
private $author = "not specified"; private $title = "not specified"; private $year = "not specified";
We have three member fields defined. Their initial value is "not specified".
$args = func_get_args();
The func_get_args()
function returns an array comprising a function's argument list. So the idea is: the code inside the constructor is dynamic; it depends on the arguments passed to it.
foreach(["title", "author", "year"] as $item) {
We go through all member fields using the foreach
keyword.
$this->$item = array_shift($args);
One of the most basic tasks in constructors is to initialize the member fields of the class. This is done by the above code line. The array_shift()
function removes the first item from the array and returns it.
$book1 = new Book("Stephen Prata", "C Primer Plus"); ... $book2 = new Book("Joshua Bloch", "Effective Java", 2008);
We have two different constructors. The first takes 2 parameters, the second takes 3.
$ php constructors.php Author: C Primer Plus Title: Stephen Prata Published: not specified Author: Effective Java Title: Joshua Bloch Published: 2008
This is the outcome of the script.
The next code example simulates constructor overloading using the factory pattern. It is one of the creational patterns in OOP. The pattern creates objects without specifying the exact class of object that will be created. More generally, the term factory method is often used to refer to any method whose main purpose is creation of objects.
factory.php
<?php class Cat { private $name = "unspecified"; private $age = "unspecified"; public static function withName($name) { $cat = new Cat(); $cat->name = $name; return $cat; } public static function withAge($age) { $cat = new Cat(); $cat->age = $age; return $cat; } public static function fullCat($name, $age) { $cat = new Cat(); $cat->name = $name; $cat->age = $age; return $cat; } public function __toString() { return "Name: $this->name, Age: $this->age\n"; } } $cici = Cat::withName("Cici"); echo $cici; $missy = Cat::withAge(6); echo $missy; $lucky = Cat::fullCat("Lucky", 4); echo $lucky; ?>
We have a Cat
factory class in the above PHP script. It has three different static functions. Each of them returns a specific cat object.
private $name = "unspecified"; private $age = "unspecified";
We have two member fields. Their initial value is "unspecified".
public static function withName($name) { $cat = new Cat(); $cat->name = $name; return $cat; }
Here is a static withName()
function. This function creates an instance of the Cat
class. It sets the name
member field and returns the object.
$cici = Cat::withName("Cici"); echo $cici;
We create an instance of the cat with one of the factory methods. We echo the object. i.e. call the __toString()
method of the class.
$ php factory.php Name: Cici, Age: unspecified Name: unspecified, Age: 6 Name: Lucky, Age: 4
The output of the script.
In this part of the PHP tutorial, we continued the discussion of the object-oriented programming in PHP.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论