PHP sınıfı yöntemlerini tanımlama

10 Cevap php

Sınıf tanımının dışında bir sınıfın yöntem bildirmek için (o C + + gibi) PHP içinde mümkün mü?

10 Cevap

Hayır, PHP 5.2 gibi. Ancak, işlev veya yöntem arbitraty aramak iletmek için __call sihirli yöntemini kullanabilirsiniz.

class A {

    public function __call($method, $args) {
        if ($method == 'foo') {
            return call_user_func_array('bar', $args);
        }
    }

}

function bar($x) {
    echo $x;
}

$a = new A();
$a->foo('12345'); // will result in calling bar('12345')

Gelen PHP 6 traits için (büyük olasılıkla) destek olacaktır. Sürekli bağımsız nesne olarak örneği olamaz yöntem (ler) bir uygulamasıdır. Bunun yerine, sürekli içerdiği uygulama ile sınıfını genişletmek için kullanılabilir. Özellikleri hakkında daha fazla bilgi here.

Evet o tanımlandıktan sonra bir PHP sınıfı için bir yöntem eklemek mümkündür. Sen bir "deneysel" uzantısı olan, classkit kullanmak istiyorum. Bu uzantı, ancak varsayılan olarak etkin değildir görünür, böylece örneğin Dreamhost özel PHP ikililer izin yok (windows üzerinde eğer bir özel PHP ikili veya yük PHP dll derlemek eğer bağlıdır ve onlar kurulumu oldukça kolaydır .)

<?php
class A { }
classkit_method_add('A', 'bar', '$message', 'echo $message;', 
    CLASSKIT_ACC_PUBLIC); 
$a = new A();
$a->bar('Hello world!');

PHP kılavuzda Örnek:

<?php
class Example {
    function foo() {
        echo "foo!\n";
    }
}

// create an Example object
$e = new Example();

// Add a new public method
classkit_method_add(
    'Example',
    'add',
    '$num1, $num2',
    'return $num1 + $num2;',
    CLASSKIT_ACC_PUBLIC
);

// add 12 + 4
echo $e->add(12, 4);

Sen belki de geçersiz olabilir __call or __callStatic zamanında bir eksik yöntemi bulmak için, ama yerini ve kod çağırmak için kendi sistemini yapmak olurdu. Örneğin, yöntem çağrısı işlemek için bir "Delege" sınıf yük olabilir.

İşte bir örnek - Eğer $ foo-> bar () aramak için çalıştı, sınıf bir FooDelegate_bar sınıf oluşturmak için girişimi, ve aynı argümanlarla bunun üzerine bar () çağırır. Eğer kurmak sınıf otomatik yükleme var ise gerekli kadar, delege ayrı bir dosyada yaşayabilir ...

class Foo {

    public function __call($method, $args) {
        $delegate="FooDelegate_".$method;
        if (class_exists($delegate))
        {
             $handler=new $delegate($this);
             return call_user_func_array(array(&$handler, $method), $args);
        }


    }

}

Hayır.

Eğer yardımcı olur, ama, daha önce ilan sınıfları uzatabilirsiniz.

Ian Selby written an article üzerinde bulunur. Onun çözümü iyi görünüyor.

PHP 5.3 kapanışları destekler gibi, dinamik kapanışları tutan değişkenler olarak örnek yöntemleri tanımlayabilirsiniz:

$class->foo = function (&$self, $n) {
  print "Current \$var: " . $self->var . "\n";
  $self->var += $n;
  print "New \$var:     " .$self->var . "\n";
};

$self, bir referans olarak (siz $this nesne bağlamı dışında kullanamazsınız) alarak (&), sen örneğini değiştirebilirsiniz.

Normal işlevini çağırmak çalıştığınızda Ancak, sorunlar oluşabilir:

$class->foo(2);

Sen önemli bir hata alıyorum. PHP foo çünkü sözdizimi, $class bir yöntem olduğunu düşünüyor. Ayrıca, ilk argüman olarak örneğini geçmelidir.

Denilen adıyla işlevleri çağırmak için özel bir fonksiyon neyse ki vardır call_user_func:

call_user_func($class->foo, &$class, 2);
# => Current $var: 0
# => New $var:     2

Sadece örnek değişkeni önce & koymak unutmayın.

Eğer __call sihirli yöntemi kullanırsanız, Ne de kolay değildir:

class MyClass {
  public function __call ($method, $arguments)  {
    if (isset($this->$method)) {
      call_user_func_array($this->$method, array_merge(array(&$this), $arguments));
    }
  }
}

Şimdi bunun yerine $class->foo(2) arayabilirsiniz. Sihirli __call yöntem bilinmeyen bir yöntemi çağrısı yakalar ve denilen yöntemi olarak aynı adla $class->foo değişkene kapatma çağırır.

$class->var Özel olsaydı tabii ki, $class->foo değişken depolanan içinde kapatma erişmek mümkün olmaz.

Hayır o durum değildir. Eğer inşa fonksiyon / metod dışında sınıfını tanımlamak eğer küresel fonksiyonu olur.

C + + ya da bunu yapamaz. Eğer de birlikte beyanı karıştırmak mı finition?

Herkesin dediği gibi Hayır, bu kesinlikle mümkün değildir.

Ancak, something like this PHP bir mixin taklit ya da almak için gidiyoruz gibi yaklaşık olarak yakındır zamanında bir sınıf yöntemleri eklemek yapabilirsiniz. Temelde, sadece aynı işlevselliği elde etmek için tasarım desenleri kullanıyor. Zope 3 Python, bunları doğrudan desteklemeyen başka dilde Katmalar taklit benzer bir şey yapar.

Necesity beyan ve sınıf bildirimi dışında işlevini tanımlamak hem de, sen gerçekten 2 çözümleri var:

a) the __call magic method that can decide a suitable outcome to the request; b) the extension that not all hosts allow;

İlk seçenek büyük olasılıkla kullanılan ve 2 şekilde kullanılabiliyor.

Eğer geçmek zorunda "$ bu" bir argüman olarak ve don 'değil, sınıf bağlamda, global bağlamda işlevi yazmak zorunda olacaktır: a) 1) eksik yöntemi (olumsuz bir Lue bazı genel işlevini çağırmak t / özel korumalı bir değişken) iç erişebilirsiniz. Fonksiyon harici bir dosyada ya da değilse farketmez.

siz dahil ne dosya belirlemek için bir içerme mekanizması gerekir) prosedürü dış dosyaya olmak zorundadır: a) 2) bu yüzden hala (dezavantajı tam sınıf bağlamı olacak içinde eksik yöntemler tüm prosedürü olan bazı dış içerme dosyası

BTW: i PHP sınıfı (C + + davranış) dışında yöntem gövdeleri tanımlayan kabul görmeye çalıştığınız bu yazı bulundu.

Ben yukarıda söylediğim gibi zamanında bir sınıf yeni bir yöntem tanımlayan + bildirerek yapılabilir biliyordu, ama PHP en azından sınıf içinde bir işlev bildirmek izin ve ben bir sınıf bildirimi parçalamadan düşünüyordum (dışında tanımlamak umuyordum Birden fazla dosya içine bir yöntemi içeren her dosya).

Herkes ne PHP6 ilgili bu gibi olacak bir ipucu var mı?