Ne avantajı PHP nesne aşırı yüklenmelerden sağlanır?

8 Cevap php

PHP nesne aşırı yükleme açıklanmıştır here.

Temelde bir ulaşılmaz nesne özelliği veya yöntemi erişildiğinde bazı özel eylemler tanımlamanızı sağlar.

Bu özellik için bazı pratik kullanımları nelerdir?

8 Cevap

Eğer bir 3. parti API ya da ne zaman yöntem / üyeler yapısı belirsizdir ile iletişim Genellikle, bu yöntemleri yararlıdır.

Diyelim ki genel bir XML-RPC sarıcı yazıyor diyelim. Eğer GBM Dosyayı indirmeden önce size mevcut yöntemlerini bilmiyorum bu yana, aşırı yükleme kullanmak mantıklı.

Daha sonra, bunun yerine aşağıdaki yazma:

$xmlrpc->call_method('DoSomething', array($arg1, $arg2));

Sen kullanabilirsiniz:

$xmlrpc->DoSomething($arg1, $arg2);

Hangi daha doğal bir sözdizimi.


Ayrıca yöntem, değişken nesneler için aşırı yükleme gibi aynı şekilde üye aşırı yüklenmesini kullanabilirsiniz.

Eğer izlemek istediğiniz sadece tek bir şey: Sadece değişken yapısı nesnelere kullanımını sınırlamak veya sadece alıcılar ve setters sözdizimsel kısayolları için kullanabilirsiniz. Birden yöntemlerle iş mantığı ayırmak için sınıfta alıcı ve ayarlayıcıları tutmak mantıklı, ama bir kısayol olarak kullanarak yanlış bir şey yok:

class ShortcutDemo {
  function &__get($name) {
    // Usually you want to make sure the method
    // exists using method_exists, but for sake
    // of simplicity  of this demo, I will omit
    // that logic.
    return call_user_method('get'.$name, $this);
  }

  function __set($name, &$value) {
    return call_user_method('set'.$name, $this, $value);
  }

  private $_Name;

  function &getName() { return $this->_Name; }
  function setName(&$value) { $this->_Name = $value; }
}

Doğrulamak ve ayarlamak verilerinizi, ve hala gibi sözdizimsel kısayolları kullanmak için alıcı ve ayarlayıcıları kullanmaya devam edebilirsiniz bu şekilde:

$shortcut->Name = 'Hello';

Andrew söz etmedi (ya da yazma sırasında söz değil) başka bir yöntem alıcılar ve belirleyiciler kurtulmak içindir. Bunun yerine her setter bildirmek ve bu gibi gaz giderici zorunda:

$obj->setName("Chacha");
$obj->setRep(10000000000000000000000);

Bunu yerine sadece yapabilirsiniz

$obj->Name = "chacha";
$obj->Rep = 100000000000000000;

İkinci yöntem daha doğal.

Sihirli Yöntemler temelde Object Oriented programlama düşünce ve bir iş uygulamak nasıl dış dünyaya önemli değil gerektiği fikrini ilerletmek. Sihirli Yöntemleri sayesinde, istediğiniz ancak sizin değişkenleri saklamak ve sadece diğer sınıflar doğal bir şekilde bunları ayarlamak izin verir.

Örnek: Ben gerçekten kolay oturumuna tüm kadar itmek için yineleme yapmak için yapacak tek bir dizideki bütün kullanıcının hesap tercihlerini saklamak olabilir.

Bunun için bir Sihirli Yöntemi kullanmak vermedi, ben setleri bir demet yapmak zorunda ya olur, daha fazla kod yazma anlamına gelir, ya da uygulama ortaya diziye, doğrudan erişim sağlayacak, bu yüzden ben gidemem istiyorum ya ve daha sonra değiştirin.

Bunun yerine, Sihirli Yöntemler kullanarak, ben sadece onları düzenli değişkeni ayarlamak var, ve ben içten onunla başa.

Bir sınıf isset ve unset için karmaşık kuralları vardır Sen durumlar için kullanabilirsiniz. Örneğin, bir değişken $ a içeren bir sınıf nesneleri veya diğer kaynakların bir dizi olabilir, ve ne zaman unset, diğer bazı işlevleri yerine yapmak zorunda.

Onlar olmayan bir özel mülkiyet yeni bir özellik ve almak ekleyerek, ancak mülkiyet / üye değişkeni adını bağlı diğer kodu çağırarak bir nesnenin iç durumu değiştirmek için kullanabilirsiniz izin neden emin değilim gerçi ayarlanmaktadır.

Bazı durumlarda, bu C + + operatör overloading benzer

Eğer polimorfizmi (diyelim ki, sen kontrol edemez bir kütüphane sınıfını kullanarak konum) bir seçenek değildir nesneleri oluşan veya toplanan olduğunda iletmeyi mesaj.

<?php

// Class A is final, so we can't make subclasses.
final class A
{
  public function hello( $callback )
  {
    echo call_user_func( $callback, 'hello world' );
  }
}

// so instead, we make a wrapper class that will take an instance
// of A as an aggregate
class B
{
  private $a;

  public function __construct( A $a )
  {
    $this->a = $a;
  }

  // this mimics inheritance on the aggregate object
  // method calls are automatically forwarded to instance of A
  // if they are valid
  public function __call( $method, $args )
  {
    if ( method_exists( $this->a, $method ) )
    {
      return call_user_func_array( array( $this->a, $method ), $args );
    }
    throw new Exception( "Method [$method] not found." );
  }
}

class C extends B
{
  // This mimics overriding an "inherited" method
  public function hello( $callback )
  {
    echo call_user_func( $callback, 'bonjour le monde' );
  }
}

$a = new A;

$b = new B( $a );
$c = new C( $a );

$b->hello( 'strtoupper' );
$c->hello( 'strtoupper' );

Bu özellik, onun mucidi Alan Kay zihninde, aslında what object oriented programming is all about olduğunu: Nesneler birbirlerine mesaj gönderme ve potansiyel mesajın her türlü tepki. Derleme zamanında sabit Yöntemleri Bu kavramın sınırlı (ama aynı zamanda daha verimli) uygulaması vardır. Kay'in ünlü-alıntı "Ben odaklı terim nesne icat ve C + + aklımda değil ne olduğunu söyleyebilirim." İşte burada gelmektedir.

Temel olarak, nesneleri yöntemine tepki izin nesne yönelimi geniş tanımı, derleme zamanında sabit gelen bir yöntem bu orijinali uygulayan kalmadan çağırır. En modern "dinamik" dil bir form veya başka bunu destekliyoruz.

Bunun için neyin iyi gelince: iyi bir örnek için Groovy's Builders bakabilirsiniz. Temel olarak, bu veri içine yöntem adlarını kendileri çevirerek, çok kompakt düşük fazlalık sözdizimi sağlar.

Ben kullandım ki, biraz meraklısı olan bir yolu, Nesne İlişkisel Yönetimi gibi bir Linq (ORM) sistemi oluşturmaktır. Eğer bir veritabanı tablo yapısını yük ve sadece bir nesne sanki (veritabanı tablosundan) verileri manipüle nerede.

yani

include('blibrary/bLinq.class.inc');

$linq = new bLinq(new bLinqSql('mysql://dsn'));
$r = $linq->from('Users')
          ->password
          ->select();

hangi aşağıdaki SQL çevirir:

SELECT `password` from Users;

password select deyiminde aşırı yöntemi geliyor.

Sonuç aşağıdaki gibi kullanılabilir:

(array)$r->password;   // which outputs an array multiple results of password;
(string)$r->password;  // which outputs a string of the first password hash;
$r->password[2];       // which outputs a string of the third password hash;

Nokta programlarken kelime "password" anında veritabanındaki başka bir alan için ikame edilebilir olmasıdır.

Ben kullanmak __ örneğin nesneleri birbirine bağlamak için set almak ve __

$user = new User();
echo $user->Profile->views;

Bu (genellikle) users.id = profile.user_id bağlayan bazı SQL çağırır.

(Python ya da C # gibi) özellikleri. Eğer böyle bir şey in Nette, kamu gibi bazı özellik gösteren bazı sınıfını oluşturmak kullanın, örneğin:

<?php
class Foo extends Object
{
    public $bar;
}

Bu özellik doğal bir şekilde erişebilirsiniz - $instance->bar. Vb bazı doğrulama yapmak istiyorum ama ne zaman, sadece alıcı ve ayarlayıcı ekleyin:

<?php
class Foo extends Object
{
    private $bar;

    public function getBar()
    {
        return $this->bar;
    }

    public function setBar($bar)
    {
        if ($bar === NULL) throw new Exception('…');
        $this->bar = $bar;
    }
}

Ve hala kullanabileceğiniz $instance->bar. Ama bunu yaptığınızda $instance->bar = NULL;, aramadan gibi $instance->setBar(NULL);.