views:

1819

answers:

6

Trying to figure out whether PHP supports features like method overloading, inheritance, and polymorphism, I found out:

  • it does not support method overloading
  • it does support inheritance

but I am unsure about polymorphism. I found this Googling the Internet:

I should note that in PHP the polymorphism isn't quite the way it should be. I mean that it does work, but since we have a weak datatype, its not correct.

So is it really polymorphism?

Edit Just can't quite place a definite YES or NO next to PHP supports polymorphism. I would be loath to state: "PHP does not support polymorphism", when in reality it does. Or vice-versa.

+2  A: 

You can still override methods, just not overload them. Overloading (in C++) is where you use the same method name for multiple methods, differing only in number and types of parameters. This would be hard in PHP since it's weak-typed.

Overriding is where the sub-class replaces a method in the base class. Which is really the basis for polymorphism, and you can do that in PHP.

GoatRider
sorry, this is not exactly what I meant. I understand why method overloading is not supported in PHP, and the difference between overloading and overriding. But can I proclaim it does support polymorphism?
Peter Perháč
+11  A: 
class Animal {
    var $name;
    function __construct($name) {
        $this->name = $name;
    }
}

class Dog extends Animal {
    function speak() {
        return "Woof, woof!";
    }
}

class Cat extends Animal {
    function speak() {
        return "Meow...";
    }
}

$animals = array(new Dog('Skip'), new Cat('Snowball'));

foreach($animals as $animal) {
    print $animal->name . " says: " . $animal->speak() . '<br>';
}

You can label it all you want, but that looks like polymorphism to me.

Paolo Bergantino
sure, but the Animal interface does not specify there will be a speak() method. So I could construct an object like new FPDF(); and then add it to the array of animals. What then? How would it speak() ?
Peter Perháč
You can specify a speak method in the Animal class, and it would be called if the child class does not specify its own speak. And if it does, you can call it anyways with parent::speak();
Paolo Bergantino
So you would say it DOES support polymorphism. I am thinking of calling it 'unsafe' or 'weak polymorphic behaviour'. what's your opinion?
Peter Perháč
unsafe and weak aren't words I'd use, to be honest. PHP does also support method overloading as Till shows, but it's not nearly as clean as it should be. I'd say it has polymorphism, all things considered.
Paolo Bergantino
Thanks. When you say `unsafe and weak aren't words i'd use`, are you hinting that maybe you'd call it something else? `not nearly as clean` perhaps?
Peter Perháč
Yeah, maybe not as clean as it could be, but it's fine for the most part.
Paolo Bergantino
+1  A: 

__call() and __callStatic() should support method overloading. More on this is available in the manual. Or what exactly are you after?

UPDATE: I just noticed the other replies.

For another way to overload a method, consider the following:

<?php
public function foo()
{
    $args = func_get_arg();
}

Certainly not pretty, but it allows you to do virtually whatever you want.

Till
this is a nice hack :) good to keep in "tule box" :)
Peter Perháč
tool box? :) Hehe... yeah, just remember, to not use it. Also, in case you are after monkey patching, look into runkit.
Till
"Homer's Tule Box" is what Homer Simpson has written on his toolbox. :)
Pekka
A: 

Some call this duck typing.

Martin
Quack!! Quack!!
SeanJA
+2  A: 

although PHP does not support method overloading the way you have experienced in other languages, say Java. but you CAN have method overloading in PHP, but the definition method is different. if you want to have different functionality for a given method, with different set of parameters in PHP, you can do something like this:

class myClass {
    public function overloadedMethod() {
        // func_num_args() is a build-in function that returns an Integer.
        // the number of parameters passed to the method.
        if ( func_num_args() > 1 ) {
            $param1 = func_get_arg(0);
            $param2 = func_get_arg(1);
            $this->_overloadedMethodImplementation2($param1,$param2)
        } else {
            $param1 = func_get_arg(0);
            $this->_overloadedMethodImplementation1($param1)
        }
    }

    protected function _overloadedMethodImplementation1($param1) {
        // code 1
    }

    protected function _overloadedMethodImplementation2($param1,$param2) {
        // code 2
    }
}

there could be cleaner implementation, but this is just a sample.

PHP supports inheritance and interfaces. so you can have polymorphism using them. you can have an interface like this:

// file: MyBackupInterface.php
interface MyBackupInterface {
    // saves the data on a reliable storage
    public function saveData();
    public function setData();
}

// file: myBackupAbstract.php
require_once 'MyBackupInterface.php';
class MyBackupAbstract implements MyBackupInterface {
     protected $_data;
     public function setData($data) {
         $this->_data= $data;
     }
     // there is no abstract modifier in PHP. so le'ts avoid this class to be used in other ways
     public function __construct() {
          throw new Exception('this class is abstract. you can not instantiate it');
     }
}

// file: BackupToDisk.php
require_once 'MyBackupAbstract.php';
class BackupToDisk extends MyBackupAbstract {
     protected $_savePath;

     // implement other methods ...

     public function saveData() {
           // file_put_contents() is a built-in function to save a string into a file.
           file_put_contents($this->_savePath, $this->_data);
     }
}

// file: BackupToWebService.php
require_once 'MyBackupAbstract.php';
class BackupToWebService extends MyBackupAbstract {
     protected $_webService;
     // implement other methods ...

     public function saveData() {
           // suppose sendData() is implemented in the class
           $this->sendData($this->_data);
     }
}

now in your application, you might use it like this:

// file: saveMyData.php
// some code to populate $myData
$backupSolutions = array( new BackupToDisk('/tmp/backup') , new BackupToWebService('webserviceURL') );
foreach ( $backupSolutions as $bs ) {
    $bs->setData($myData);
    $bs->saveData();
}

you are right, PHP is not strong typed language, we never mentioned that any of your $backupSolutions would be a 'MyBackupAbstract' or 'MyBackupInterface', but that would not stop us from having the nature of polymorphism which is different functionality over using the same methods.

farzad
+1 for a nice answer
Peter Perháč
A: 

Sorry, I tried to commend on farzad's answer but couldn't - perhaps someone more familiar can change this to a comment?

farzad - // there is no abstract modifier in PHP. so le'ts avoid this class to be used in other ways

How do you mean? Your class could have been written as:

abstract class ClassName implements MyInterface { /* abstract implementation */ }

That's perfectly valid and stops the class being instantiated

searbe