PHP This! A Beginners Guide to Learning Object Oriented PHP. Michelle Gosney
you need. That is the fundamental goal of polymorphism.
Polymorphism is a mechanism by which objects of different types can process data through a single interface.
Using a typical illustrative example, a program might define a type of object called Animal, containing a function called speak() and, through inheritance, derive object sub-types such as Cow, Dog, etc. that each have their own specific implementation of the speak() function. The mechanism of polymorphism allows such a program to call the speak() function without actually knowing whether it is calling it for a Cow, Dog, or any other derivative Animal, while executing the correct function for the specific type of Animal.
Polymorphism is not the same as method overloading or method overriding (in OOP, a method is a function that belongs to a class, while the class variables are referred to as its members) and should not be confused with these.
Method Overloading
Method overloading is where a class has two or more functions of the same name, but accepting a different number and/or data types of parameters.
Method Overriding
Method overriding is where a child class (one derived through inheritance) defines a function with the same name and parameters as a function in its parent class, but provides a different implementation of the function. This is not the same as polymorphism, as it does not necessarily involve late-binding, however overriding is part of the mechanism by which polymorphism is accomplished.
All this can sound confusing at first but a simple code example can help clarify:
This is an example of overriding. It is different from polymorphism because we are declaring a Cow and directly calling a Cow function through Cow’s interface. However, PHP is a loosely-typed language, meaning that the vast majority of data type handling is done implicitly by PHP, rather than the programmer. This means the difference between overriding and polymorphism in PHP can appear rather subtle. Consider a slightly different example:
Late Binding / Dynamic Binding
Late-binding (also known as dynamic binding) is the mechanism by which polymorphism is accomplished. In the example above, the speak() function is defined in the base class, but makes a call to getName(), a polymorphic function that has a specific implementation in each child class. Late-binding means that it is only at runtime, when the function is called, that the specific data type is bound to the request. In simple terms, even though speak() is defined only in the generic Animal class, it will call the child-specific implementation of getName(). This late-binding is a relatively new feature of PHP and is what makes true polymorphism possible.
This example is polymorphism, because the Name() function knows it is receiving an object of type Animal, but not whether it is a Cow, Dog or whatever else. Notice how we have specified type Animal as a parameter for the Name() function – specifying the data type of function parameters is normal and required in strongly-typed languages, but this type hinting is optional in PHP. Specifying a type hint will cause PHP to generate a fatal error if you attempt to pass the function a non-object, or object of a different type.
PHP is a dynamic programming language because it executes many common behaviors at run time that other languages might perform at compile time. It is loosely typed, or dynamically typed, in that a majority of the type checking is performed at run-time as opposed to being done at compile time. In dynamic typing values have types but variables do not, that it, a variable can refer to any value of any type.
Chapter 2: Magic Methods
The magic methods are reserved method names you can use in your classes to utilize special PHP functionality. Magic methods provide access to special PHP behavior. The naming convention used for magic methods is a lower/camel-case letters with two leading underscores.
__construct()
The constructor is a magic method that gets called when the object is instantiated, that is, at the moment an instance a class is created. It is usually the first thing in the class declaration but it does not need to be, it is a method like any other and can be declared anywhere in the class. Recall when I mentioned the parenthesis after the Person class name when we instantiated Mindi?
The reference to the Person() class is the constructor for the $Mindi object. In this particular case the constructor is not implemented because there is nothing inside the parenthesis. By this I mean we don’t initialize any of $Mindi’s properties when we call the constructor. If we do not define a constructor function in our class then the PHP engine will assume that we are using an unimplemented constructor, that is:
Constructors also inherit like any other method. So if we consider our previous inheritance example from the Introduction to OOP, we could add a constructor to the Animal class like this:
Now we can create a class which inherits from the Animal class. Without adding anything into the Cow class, we can declare it and have it inherit from Animal, like this:
If we define a __construct method in the Cow class, then Cow objects will run that instead when they are instantiated. Since there isn’t one, PHP looks to the parent class definition for information and uses that. So we can override, or not, in our new class – very handy.
Invoking Parent Constructor and Destructor
We can get the parent PHP5 constructor and PHP5 Destructor to be invoked in the same way as invoking the parent method, refer to the example below:
__destruct()
Did you spot the file handle that was also part of the constructor? We don’t really want to leave things like that lying around when we finish using an object and so the __destruct method does the opposite of the constructor. It gets run when the object is destroyed, either expressly by us or when we’re not using it any more and PHP cleans it up for us. For the Animal, our __destruct method might look something like this:
__get(), __set(), __isset()
The setting and retrieval process of values of properties within a class that have no a explicit declaration comprises what's known as property overloading in PHP. The __set() function will be called automatically by the PHP engine each time a script attempts to assign a value to a property of a class that hasn't been explicitly declared. The __get() function will be invoked transparently when a script tries to retrieve the value of an undeclared class property. The __isset() function is also invoked when it is called on an undefined property.