2009-08-11 11 views

risposta

4

Di solito, questi metodi sono utili quando si comunica con un'API di terze parti o quando la struttura metodo/membri non è chiara.

Diciamo che state scrivendo un wrapper XML-RPC generico. Dato che non conosci i metodi disponibili prima di scaricare il file WDL, è logico utilizzare il sovraccarico.

Poi, invece di scrivere il seguente:

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

È possibile utilizzare:

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

che è una sintassi più naturale.


È inoltre possibile utilizzare l'overloading dei membri allo stesso modo dell'overload del metodo per oggetti variabili.

Solo una cosa che si desidera osservare: limitarne l'uso solo agli oggetti a struttura variabile o utilizzarla solo per le scorciatoie sintattiche per getter e setter. Ha senso mantenere getter e setter nella classe di separare la logica di business in diversi metodi, ma non c'è nulla di male a utilizzarlo come scorciatoia:

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

In questo modo è possibile continuare a utilizzare i tuoi getter e setter per la convalida e impostare i dati e comunque utilizzare le scorciatoie sintattiche come tale:

$shortcut->Name = 'Hello'; 
0

Un altro metodo che Andrew non ha menzionato (o non ha menzionato, al momento della scrittura) è per sbarazzarsi di getter e setter. Invece di dover dichiarare ogni setter e getter in questo modo:

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

Si può invece fare solo

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

Il secondo metodo è più naturale.

I Metodi magici fondamentalmente portano avanti il ​​pensiero della programmazione orientata agli oggetti, e l'idea che il modo in cui implementate un lavoro non dovrebbe importare al mondo esterno. Attraverso i Metodi Magici, ti permette di memorizzare le tue variabili come vuoi, e semplicemente lasciare che le altre classi le impostino in modo naturale.

Esempio: potrei memorizzare tutte le preferenze dell'account del mio utente in un singolo array che renderebbe molto facile iterare fino a spingerlo fino alla sessione.

Se non ho usato un metodo magico per questo, dovrei fare un sacco di set o get, il che significa scrivere più codice, o consentire l'accesso diretto alla matrice, che rivela l'implementazione, così io non posso andare e cambiarlo più tardi.

Invece, usando i Metodi Magici, ho appena impostato la variabile regolarmente e la gestisco internamente.

+0

Anche se non mi libererei ancora di getter e setter. Più metodi contenenti regole di business per le varie proprietà individuali sono in genere più facili da gestire e eseguire il debug di un metodo enorme contenente tutte le regole aziendali per tutte le proprietà. Userei solo '__get()' e '__set()' per un modo rapido di chiamare 'getX',' setX'. L'uso dell'overload dell'oggetto deve essere mantenuto solo per oggetti a struttura variabile. –

+0

Leggi la mia versione aggiornata. –

+0

Tuttavia, questo non funziona come C# Get/Set Property. Almeno non così flessibile, se si desidera verificare o convalidare ciò che viene impostato. – Extrakun

0

È possibile utilizzarlo per i casi in cui una classe ha regole complesse per isset e unset. Ad esempio, una classe contenente una variabile $ a potrebbe essere una matrice di oggetti o altre risorse e, quando non impostati, devono eseguire alcune altre funzionalità.

Anche se non sono sicuro del motivo per cui consentono l'aggiunta di una nuova proprietà e il recupero di una proprietà non privata, ma è possibile utilizzarlo per modificare lo stato interno di un oggetto chiamando un altro codice in base al nome del variabile proprietà/membro impostata.

In alcuni casi, questo assomiglia overloading degli operatori in C++

0

inoltro dei messaggi per gli oggetti quando si è composti o aggregate in cui il polimorfismo non è un'opzione (ad esempio, si sta utilizzando una libreria di classi non si può controllare).

<?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'); 
0

Questa funzione è in realtà what object oriented programming is all about, nella mente del suo inventore Alan Kay: Oggetti invio di scambiarsi messaggi, e potenzialmente reagire a qualsiasi tipo di messaggio. I metodi risolti al momento della compilazione sono un'implementazione limitata (ma anche più efficiente) di questo concetto. Ecco dove la famosa frase di Kay "Ho inventato il termine object oriented, e posso dirti che il C++ non era quello che avevo in mente." viene da.

Fondamentalmente, consentire agli oggetti di reagire alle chiamate di metodo senza avere un metodo corrispondente fissato in fase di compilazione implementa questa originale e più ampia definizione di orientamento dell'oggetto. La maggior parte delle moderne lingue "dinamiche" la supportano in una forma o nell'altra.

Per ciò che è buono: dare un'occhiata a Groovy's Builders per un buon esempio. Fondamentalmente, consente una sintassi a ridondanza ridotta molto compatta trasformando i nomi dei metodi stessi in dati.

0

Un modo, un po 'più elaborato, che ho usato è quello di creare un sistema Linq come Object Relational Management (ORM). Dove puoi quindi caricare una struttura di tabella del database e manipolare i dati (dalla tabella del database) come se fosse solo un oggetto.

cioè

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

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

che traduce il seguente SQL:

SELECT `password` from Users; 

Il password nell'istruzione select deriva dal metodo di overload.

Il risultato può essere utilizzato come:

(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; 

Il punto è che la parola "password" potrebbe essere sostituito per qualsiasi altro campo nel database al volo durante la programmazione.

0

Uso __get e __set per collegare insieme gli oggetti, ad es.

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

Questo (in genere) chiama alcuni collegamenti SQL users.id = profile.user_id.

0

Proprietà (come quella in Python o C#).Per esempio, quando si utilizza qualcosa di simile in Nette, si crea una classe, che mostra alcune proprietà come pubblico:

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

È possibile accedere a questa proprietà modo naturale - $instance->bar. Ma quando si vuole fare un po 'di convalida, ecc, si aggiunge solo getter e setter:

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

E ancora si utilizza $instance->bar. Ma quando fai $instance->bar = NULL;, è come chiamare $instance->setBar(NULL);.

Problemi correlati