Ne polimorfizm gerçekten PHP biçimlilik gibi görünüyor mi?

9 Cevap php

PHP yöntem overloading, miras ve çok biçimlilik gibi özellikleri destekler olmadığını anlamaya çalışıyorum, ben öğrendim:

  • Bu yöntem aşırı yüklenmesini desteklemez
  • Bu destek miras yok

ama ben polimorfizmi hakkında emin değilim. Bu İnternet Googling bulunan:

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.

Yani gerçekten polimorfizmidir?

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.

9 Cevap

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>';
}

Bunu istediğiniz her etiket olabilir, ama bu benim için çok biçimlilik gibi görünüyor.

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
    }
}

Orada temiz uygulama olabilir, ama bu sadece bir örnek olabilir.

PHP miras ve arabirimleri destekler. böylece bunları kullanarak poliformizme sahip olabilir. Eğer böyle bir arayüze sahip olabilir:

// 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);
     }
}

şimdi uygulama, bu gibi kullanabilirsiniz:

// 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();
}

haklısın, PHP biz $ backupSolutions herhangi bir 'MyBackupAbstract' veya 'MyBackupInterface' olacağını asla söz, güçlü yazılı dil değil, ama bu kullanarak farklı işlevsellik polimorfizminin doğasını olması bizi durdurmak olmaz Aynı yöntemleri.

__call() ve __callStatic() yöntemi aşırı yüklenmesini desteklemelidir. Bu konuda daha fazla manual mevcuttur. Veya tam sonra ne?

UPDATE: Ben sadece diğer yanıtları fark ettim.

Bir yöntem aşırı için başka bir yol, aşağıdakileri dikkate alın:

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

Kesinlikle güzel, ama sen istersen hemen yapmanızı sağlar değil.

Sen hala onları aşırı değil, yöntemlerini geçersiz kılabilirsiniz. Sadece sayı ve parametrelerinin türleri farklı, birden fazla yöntem için aynı yöntem adını kullanmak nerede (C + +) 'dir aşırı yüklenmesi. Zayıf-yazdığınız beri bu PHP zor olurdu.

Alt sınıf taban sınıftaki bir yöntemini değiştirir nerede basan olduğunu. Gerçekten polimorfizmi için temel olduğunu ve PHP bunu hangi.

Bazı çağrı bu duck typing.

PHP Diğer dillerde bir derleme hatası üretecektir polimorfik kod sağlar. Basit bunu göstermektedir. Beklenen bir derleme hatası üretir İlk C + + kodu:

class Base {};

class CommonDerivedBase {
   public:
    // The "= 0" makes the method and class abstract
    // virtual means polymorphic method
    virtual whoami() = 0;
};

class DerivedBase : public CommonDerivedBase {
   public:    
     void  whoami() { cout << "I am DerivedBase \n"; }
};

class Derived1 : public CommonDerivedBase {
  public:
    void  whoami() { cout << "I am Derived1\n"; }
};

class Derived2 : public CommonDerivedBase {
public:
 void whoami() { cout <<  "I am Derived2\n"; }
};

/* This will not compile */
void  test_error(Base& db)
{
   db.whoami();
}

C + + derleyicisi hattı için bu hata mesajını verecek db.whoami()

error: no member named 'whoami' in 'Base'

Temel yöntem olarak adlandırılır whoami yoktur (çünkü). Ancak, benzer PHP kodu çalıştırma kadar gibi hataları bulmak değil.

class Base {}

abstract class DerivedCommonBase {
  abstract function whoami();
}

class Derived1 extends DerivedCommonBase {

 public function whoami() { echo "I am Derived1\n"; }
}

class Derived2 extends DerivedCommonBase {

 public function whoami() { echo "I am Derived2\n"; }
}

/* In PHP, test(Base $b) does not give a runtime error, as long as the object 
 * passed at run time derives from Base and implements whoami().
 */
function test(Base $b)
{
  $b->whoami(); 
}

$b = new Base();
$d1 = new Derived1();
$d2 = new Derived2();

$a = array();

$a[] = $d1;
$a[] = $d2;

foreach($a as $x) {

  echo  test($x);
}

test($d1);
test($d2);
test($b); //<-- A run time error will result.

Foreach döngü çıkışı ile çalışır

I am Derived1
I am Derived2

Eğer test ($ b) arayın ve Base bir örneğini geçemiyor kadar senin bir çalışma zamanı hatası alırsınız. Yani foreach, çıkış olacak sonra

I am Derived1
I am Derived2
PHP Fatal error:  Call to undefined method Base::whoami() in
home/kurt/public_html/spl/observer/test.php on line 22

About the only thing you can do to make the PHP safer would be to add a run time check to test if $b is an instance of the class you intended.

function test(Base $b)
{
  if ($b instanceof DerivedCommonBase) {
     $b->whoami(); 
  } 
}

Ama polimorfizminin bütün mesele bu tür çalışma süresi kontrolleri ortadan kaldırmaktır.

PHP sınıf-tabanlı polimorfizm vardır, ama argüman tabanlı polimorfizmini uygulanması için resmi bir mekanizma yoktur.

Sınıf bazlı polimorfizmi bir taban sınıfta açısından düşünmek ve çağrılan yöntemleri son sınıfa bağlı olabileceği anlamına gelir. Böyle Üçgen ve Çember gibi çeşitli sınıfların nesneleri bir dizi var, ve bu sınıfların her biri aynı class Shape uzanır Örneğin, sen şekillerin sadece bir koleksiyon olarak diziyi kabul edebilirsiniz. Sen şekiller aracılığıyla döngü can ve her şeklin getArea () yöntemini çağırın. Çağrıldığını getArea () yöntemi, nesne sınıfı bağlıdır sayede Polimorfizma olgudur. Sizin şekil Üçgen, Üçgen ise :: getArea () çağrılır, bir daire, daha sonra daire :: getArea () denilen alırsa - kodunuz Circle ve Üçgen ayırt etmez bile ama her nesneyi ilgili olarak sadece bir şekli. Farklı bir kod bloğu kod sonuçlarının aynı hat nesnenin sınıfına bağlı olarak yürütülmektedir.

Argüman tabanlı polimorfizm farklı parametreler olması koşuluyla aynı adı birden çok yöntem tek bir sınıfta tanımlanabilir buradaki bazı güçlü-yazdığınız dilde, bir özelliğidir; O yöntemi denir sağlanan argümanlar bağlıdır. Elle yöntemi içinde argüman türlerini dikkate PHP gibi zayıf-yazdığınız dilde argüman dayalı polimorfizmini taklit edebilirsiniz. Bu jQuery yerli argüman tabanlı polimorfizminin Javascript olmamasına rağmen bir polimorfik API uygulamak için ne yaptığıdır.

Eğer argüman tabanlı polimorfizmini uygulanması için resmi bir mekanizma sağlar spesifik demek "poliformizme destekliyorsa" tarafından Yani, cevap hayır. Herhangi geniş yorumlanması için, cevabı evet. Her Nesne Tabanlı dili sınıf-tabanlı polimorfizm destekler ve herhangi bir zayıf-yazdığınız dil argümanı tabanlı poliformizme destekler varsayımında.

Burada gördüğüm için ne php polimorfizm ve destek, ne de aşırı yükleme yöntemlerinin yok. Sen aslında bu oop işlevleri hem de yakın almak için yol kesmek olabilir, ama onlar çok bunun asıl amaç vardır. Burada örnekler çoğu ya bir sınıfın genişletilmesi veya polimorfizm emuluate için kesmek yaratıyor.

Sen sihirli yöntem __ çağrısıyla yöntem aşırı yüklenme bir yanılsama yaratmak ():

class Poly {
    function __call($method, $arguments) {
        if ($method == 'edit') {
            if (count($arguments) == 1) {

                return call_user_func_array(array($this,'edit1'), $arguments);
            } else if (count($arguments) == 2) {
                return call_user_func_array(array($this,'edit2'), $arguments);
            }
        }
    }
    function edit1($x) {
        echo "edit with (1) parameter";
    }

    function edit2($x, $y) {
        echo "edit with (2) parameter";
    }

}

$profile = new Poly();
$profile->edit(1);
$profile->edit(1,2);

Expln:

1) Here we are utilizing the power of __call() of listening calls of 
   non-available     methods and 
2) after knowing it who had called with their inputs diverting them to desired 
   method 

In php, biz working under the hood istenilen davranışı vermek ve hissi veren of method overloading için aslında