2009-08-11 10 views

Respuesta

4

Generalmente, estos métodos son útiles cuando se está comunicando con una API de un tercero o cuando la estructura del método/miembros no está clara.

Digamos que está escribiendo un contenedor XML-RPC genérico. Como no conoce los métodos disponibles antes de descargar el archivo WDL, tiene sentido usar Sobrecarga.

Entonces, en lugar de escribir la siguiente:

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

que puede utilizar:

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

que es una sintaxis más natural.


También puede usar la sobrecarga de miembros de la misma forma que la sobrecarga de métodos para objetos variables.

Solo una cosa que desea ver: limite su uso solo a objetos de estructura variable o úsela solo para accesos directos sintácticos a getters y setters. Tiene sentido mantener captadores y definidores de su clase para separar la lógica de negocio en múltiples métodos, pero no hay nada malo en utilizarlo como un acceso directo:

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

De este modo puede seguir utilizando sus métodos get y set para validar y establecer sus datos, y seguir utilizando los atajos sintácticos tales como:

$shortcut->Name = 'Hello'; 
0

Otro método que Andrew no mencionó (o no ha mencionado en el momento de la escritura) es para deshacerse de los captadores y definidores. En lugar de tener que declarar cada setter y getter así:

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

su lugar, puede simplemente hacer

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

El segundo método es más natural.

Los métodos mágicos básicamente amplían la idea de la programación orientada a objetos, y la idea de cómo implementar un trabajo no debería importarle al mundo exterior. A través de Magic Methods, te permite almacenar tus variables como quieras, y solo deja que otras clases las configuren de forma natural.

Ejemplo: Pude almacenar todas las preferencias de cuenta de mi usuario en una única matriz que facilitaría la iteración para llevarla a la sesión.

Si no utilicé un Método Mágico para esto, tendría que hacer varios conjuntos o obtener, lo que significa escribir más código, o permitir el acceso directo a la matriz, lo que revela la implementación, entonces no puedo ir y cambiarlo más tarde.

En lugar de eso, usando Magic Methods, simplemente les puse la variable regularmente, y la trato internamente.

+0

Aunque todavía no me desharía de captadores y setters. Múltiples métodos que contienen reglas de negocio para las diversas propiedades individuales generalmente son más fáciles de mantener y depurar, luego un método enorme que contiene todas las reglas comerciales para todas las propiedades. Solo usaría '__get()' y '__set()' para un acceso directo para llamar a 'getX', 'setX'. El uso de sobrecarga de objetos debe mantenerse solo para objetos de estructura variable. –

+0

Lea mi versión actualizada. –

+0

Sin embargo, esto realmente no funciona como C# Get/Set Property. Al menos no tan flexible, si desea verificar o validar lo que se está configurando. – Extrakun

0

Puede usarlo para casos en que una clase tiene reglas complejas para isset y unset. Por ejemplo, una clase que contiene una variable $ a podría ser una matriz de objetos u otros recursos, y cuando se desarman, tienen que realizar algunas otras funcionalidades.

Aunque no estoy seguro de por qué permiten la adición de una nueva propiedad y la recuperación de una propiedad no privada, pero podría usarla para cambiar el estado interno de un objeto llamando a otro código según el nombre del variable de propiedad/miembro que se está configurando.

En algunos casos, esto se asemeja a la sobrecarga de operadores en C++

0

reenvío de mensajes a los objetos cuando se ha compuesto o agregados donde polimorfismo no es una opción (por ejemplo, está utilizando una biblioteca de clases no se puede controlar)

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

Esta característica es en realidad what object oriented programming is all about, en la mente de su inventor Alan Kay: Objetos de enviar mensajes entre sí, y potencialmente reaccionar a cualquier tipo de mensaje. Los métodos fijados en tiempo de compilación son una implementación limitada (pero también más eficiente) de este concepto. Ahí es donde cita famosa de Kay: "Inventé el término orientado a objetos, y puedo decirte que C++ no era lo que tenía en mente". viene de.

Básicamente, permitir que los objetos reaccionen a las llamadas al método sin tener un método correspondiente fijado en tiempo de compilación implementa esta definición original y más amplia de la orientación del objeto. La mayoría de los lenguajes "dinámicos" modernos lo soportan de una forma u otra.

En cuanto a lo que es bueno: echa un vistazo a Groovy's Builders para ver un buen ejemplo. Básicamente, permite una sintaxis de baja redundancia muy compacta convirtiendo los nombres de los métodos en datos.

0

Una forma, que es bastante más elegante, que he usado es crear un sistema Linq como Object Relational Management (ORM). Donde puede cargar una estructura de tabla de base de datos y manipular los datos (desde la tabla de la base de datos) como si fuera solo un objeto.

decir

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

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

que se traduce en el siguiente SQL:

SELECT `password` from Users; 

El password en la instrucción de selección proviene del método sobrecargado.

El resultado puede ser utilizado como:

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

El punto es que la palabra "password" podría ser sustituido por cualquier otro campo en la base de datos sobre la marcha durante la programación.

0

Uso __get y __set para unir objetos, p. Ej.

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

Este (por lo general) llama a algunos de SQL que une users.id = profile.user_id.

0

Propiedades (como la de Python o C#).Por ejemplo cuando se utiliza algo como esto in Nette, se crea una clase, que muestra una propiedad pública como:

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

Usted puede acceder a este inmueble manera natural - $instance->bar. Pero cuando se quiere hacer algo de validación, etc., que acaba de añadir getter y 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; 
    } 
} 

Y todavía se utiliza $instance->bar. Pero cuando lo haces $instance->bar = NULL;, es como llamar al $instance->setBar(NULL);.

Cuestiones relacionadas