Documente Academic
Documente Profesional
Documente Cultură
Understanding and
Applying Polymorphism in
PHP
FEED LIKE FOLLOW FOLLOW
by Steve Guidetti 8 Sep 2010 Difficulty: Intermediate Length: Medium Languages: English
Subscribe to Access
Polymorphism is a long word for a very simple concept.
The beauty of polymorphism is that the code working with the different
classes does not need to know which class it is using since they're all used
the same way.
Interfaces
Advertisement
Translations
Interface
An interface is similar to a class except that it cannot contain code. An Envato Tuts+ tutorials are translated
1 interface MyInterface {
2 // methods
3 }
and is attached to a class using the ' implements ' keyword (multiple interfaces
can be implemented by listing them separated with commas):
Methods can be defined in the interface just like in a class, except without the
body (the part between the braces):
1 interface MyInterface {
2 public function doThis();
3 public function doThat();
4 public function setName($name);
5 }
01 // VALID
02 class MyClass implements MyInterface {
03 protected $name;
04 public function doThis() {
05 // code that does this
06 }
07 public function doThat() {
08 // code that does that
09 }
10 public function setName($name) {
11 $this->name = $name;
12 }
13 }
14
15 // INVALID
16 class MyClass implements MyInterface {
17 // missing doThis()!
18
19 private function doThat() {
20 // this should be public!
21 }
22 public function setName() {
23 // missing the name argument!
24 }
25 }
Abstract Class
An abstract class is a mix between an interface and a class. It can define
functionality as well as interface (in the form of abstract methods). Classes
extending an abstract class must implement all of the abstract methods
defined in the abstract class.
An abstract class is declared the same way as classes with the addition of
the ' abstract ' keyword:
01 class poly_base_Article {
02 public $title;
03 public $author;
04 public $date;
05 public $category;
06
07 public function __construct($title, $author, $date, $category = 0) {
08 $this->title = $title;
09 $this->author = $author;
10 $this->date = $date;
11 $this->category = $category;
12 }
13 }
Note: The example classes in this tutorial use the naming convention of
"package_component_Class." This is a common way to separate classes into
virtual namespaces to avoid name collisions.
Now you want to add a method to output the information into different
formats, such as XML and JSON. You might be tempted to do something like
this:
01 class poly_base_Article {
02 //...
03 public function write($type) {
04 $ret = '';
05 switch($type) {
06 case 'XML':
07 $ret = '<article>';
08 $ret .= '<title>' . $obj->title . '</title>';
09 $ret .= '<author>' . $obj->author . '</author>';
10 $ret .= '<date>' . $obj->date . '</date>';
11 $ret .= '<category>' . $obj->category . '</category>';
12 $ret .= '</article>';
13 break;
14 case 'JSON':
15 $array = array('article' => $obj);
16 $ret = json_encode($array);
17 break;
18 }
19 return $ret;
20 }
21 }
This is kind of an ugly solution, but it works -- for now. Ask yourself what
happens in the future, though, when we want to add more formats? You can
keep editing the class, adding more and more cases, but now you're only
diluting your class.
With this in mind, conditional statements should be a red flag indicating that
your class is trying to do too many different things. This is where
polymorphism comes in.
In our example, it is clear that there are two tasks presented: managing
articles and formatting their data. In this tutorial, we will refactor our
formatting code into a new set of classes and discover how easy it is use
polymorphism.
1 interface poly_writer_Writer {
2 public function write(poly_base_Article $obj);
3 }
It's that simple; we have defined a public write() method that accepts an
Article object as an argument. Any classes implementing the Writer interface
will be sure to have this method.
Tip: If you want to restrict the type of arguments that can be passed to your
functions and methods, you can use type hints, as we've done in the write()
As you can see from the class declaration, we use the implements keyword to
implement our interface. The write() method contains functionality specific
to formatting XML.
All of our code specific to each format is now contained within individual
classes. These classes each have the sole responsibility of handling a
specific format, and nothing else. No other part of your application needs to
care about how these work in order to use it, thanks to our interface.
1 class poly_base_Article {
2 //...
3 public function write(poly_writer_Writer $writer) {
4 return $writer->write($this);
5 }
6 }
All this method does now is accept an object of the Writer class (that is any
class implementing the Writer interface), call its write() method, passing
itself ( $this ) as the argument, then forward its return value straight to the
client code. It no longer needs to worry about the details of formatting data,
and it can focus on its main task.
Obtaining A Writer
You may be wondering where you get a Writer object to begin with, since you
need to pass one to this method. That's up to you, and there are many
strategies. For example, you might use a factory class to grab request data
and create an object:
01 class poly_base_Factory {
02 public static function getWriter() {
03 // grab request variable
04 $format = $_REQUEST['format'];
05 // construct our class name and check its existence
06 $class = 'poly_writer_' . $format . 'Writer';
07 if(class_exists($class)) {
08 // return a new Writer object
09 return new $class();
10 }
11 // otherwise we fail
12 throw new Exception('Unsupported format');
13 }
14 }
Like I said, there are many other strategies to use depending on your
requirements. In this example, a request variable chooses which format to
use. It constructs a class name from the request variable, checks if it exists,
then returns a new Writer object. If none exists under that name, an exception
is thrown to let client code figure out what to do.
Advertisement
First we created an example Article object to work with. Then we try to get a
Writer object from the Factory, falling back to a default (XMLWriter) if an
exception is thrown. Finally, we pass the Writer object to our Article's write()
Conclusion
In this tutorial, I've provided you with an introduction to polymorphism and an
explanation of interfaces in PHP. I hope you realize that I've only shown you
one potential use case for polymorphism. There are many, many more
applications. Polymorphism is an elegant way to escape from ugly
conditional statements in your OOP code. It follows the principle of keeping
your components separate, and is an integral part of many design patterns. If
you have any questions, don't hesitate to ask in the comments!
WP Translation plugin
Compatible with all Theme & Plugins (incl. WooCommerce). SEO optimized. Join
20,000 users.
Advertisement
Steve Guidetti
Recommend 11 Important
⤤ Share Update Sort by Best
When you log in with Disqus, we process personal data to facilitate your ×
Nettuts+ requires you to verify your email address before posting. Send verification email to
authentication
omondiy@gmail.com
and posting of comments. We also store the comments you
post and those comments are immediately viewable and searchable by
anyone around the world.
I agree to Disqus' Terms of Service
Join the discussion…
I agree to Disqus' processing of email and IP address, and the use of
cookies, to facilitate my authentication and posting of comments,
explained further
Darius • 6 years ago in the Privacy Policy
Advertisement
I didn't understand well - what is the point of this. I still see that there is try catch block
- it tries to get one class, if it fails, Proceed
it gets another class.
And its written that this is good to avoid if else or switch statements.
But - it still same action with try catch. Just other keywords.
Instead of complicated multiple classes, its easier to understand if else or switch. And
we always want readability, not more mess in the code, don't we?
We could make it more complicated and show other how good we are, we understand
advanced concepts. But the more important thing is simplicity, so the code could be
written and understood faster.
19 △ ▽ • Reply • Share ›
Then the lead developer paused and asked me to define polymorphism. I looked at
him as if he had three heads and got ready to get up from the chair I was squirming
in. Needless to say I didn't get the job and have done a lot more homework since. Still
have plenty to learn as far as web development goes. It's like Othello: a minute to
learn, a lifetime to master.
8△ ▽ • Reply • Share ›
Matthew, agree that PHP is easy to use and there are a lot of frameworks that you
can use to speed things up. However understanding how a car works and how it is
put together is not the same as building the car from scratch. A good understanding
of how to design OO models will greatly improve the quality of your code. It also
means you're less likely to implement something that will be a pain to maintain down
the road.
2△ ▽ • Reply • Share ›
I don't see the relation to abstract classes and interfaces, there is inheritance, but that
is not the same as polymorphism.
1△ ▽ • Reply • Share ›
It allows you to create different classes sharing same blueprints, that you absolutely
now, the classes implementing same interface, will all have the abilities described by
interface.
One usage example will be, a general database interface, and different classes
implementing different protocols to interact with MySQL,PSQL, ORACLE and even a
custom database.
echo $writer->write($article);
Instead of:
echo $article->write($writer);
But great job, it's nice to see some serious programming articles around here from
time to time.
1△ ▽ • Reply • Share ›
the poly_base_Article's function write had nothing to do with the Interface write
function except what it accepted. When first looking at it, it threw me for a loop.
I would recommend switching that name to something like "build" to avoid confusion
between the two functions. I also switched the $_request to a passed variable, since
we are already passing $title, $author, $date, $category. That way someone to test
the code and follow it through without adjusting the url for a get variable.
interface poly_writer_Writer {
public function build(poly_base_Article $obj);
}
class poly_base_Article {
public $title;
public $author;
public $date;
see more
△ ▽ • Reply • Share ›
echo $article->write($writer);
how the heck did $article have a "write" function. when $article is just a object which
contained variables( title, author, date)
AA • 6 years ago
This is awesome stuff!
Thanks.
△ ▽ • Reply • Share ›
good work....
△ ▽ • Reply • Share ›
try {
$writer = poly_base_Factory::getWriter();
}
catch (Exception $e) {
$writer = new poly_writer_XMLWriter();
}
echo $writer->write($article);
Thanks
△ ▽ • Reply • Share ›
And thanks to Tutorial City's comment that this is the Strategy Pattern. I was just
wondering if it was, and then I saw their comment!
△ ▽ • Reply • Share ›
class poly_writer_XMLWriter {
public function write(poly_base_Article $obj) {
$ret = '';
$ret .= '' . $obj->title . '';
$ret .= '' . $obj->author . '';
$ret .= '' . $obj->date . '';
$ret .= '' . $obj->category . '';
$ret .= '';
return $ret;
}
}
l l it JSONW it {
see more
△ ▽ • Reply • Share ›
Envato Market has a range of items for sale to help get you started.