Какое преимущество дает перегрузка объектов в PHP? - PullRequest
5 голосов
/ 12 августа 2009

Объяснение перегрузки PHP-объекта здесь .

По сути, это позволяет вам определять некоторые пользовательские действия при доступе к свойству или методу недоступного объекта.

Какие практические применения для этой функции?

Ответы [ 8 ]

4 голосов
/ 12 августа 2009

Обычно эти методы полезны, когда вы общаетесь с сторонним API или когда структура метода / членов неясна.

Допустим, вы пишете универсальную оболочку XML-RPC. Поскольку вы не знаете методов, доступных вам до загрузки файла WDL, имеет смысл использовать перегрузку.

Тогда вместо того, чтобы написать следующее:

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

Вы можете использовать:

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

, что является более естественным синтаксисом.


Вы также можете использовать перегрузку членов так же, как перегрузку методов для переменных объектов.

Только одна вещь, за которой вы хотите следить: ограничивайте его использование только объектами с переменной структурой или используйте его только для синтаксических ярлыков для методов получения и установки. Имеет смысл сохранить методы получения и установки в вашем классе для разделения бизнес-логики несколькими методами, но нет ничего плохого в том, чтобы использовать ее в качестве ярлыка:

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

Таким образом, вы можете продолжать использовать ваши методы получения и установки для проверки и установки ваших данных, и при этом использовать синтаксические ярлыки как таковые:

$shortcut->Name = 'Hello';
0 голосов
/ 12 августа 2009

Свойства (например, в Python или C #). Например, когда вы используете что-то подобное в Nette , вы создаете некоторый класс, который показывает некоторое свойство как public:

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

Вы можете получить доступ к этой собственности естественным путем - $instance->bar. Но когда вы хотите провести некоторую проверку и т. Д., Вы просто добавляете getter и 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;
    }
}

И все же вы используете $instance->bar. Но когда вы делаете $instance->bar = NULL;, это как звонить $instance->setBar(NULL);.

0 голосов
/ 12 августа 2009

Я использую __get и __set для связывания объектов, например,

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

Это (обычно) вызывает SQL-соединение, связывающее users.id = profile.user_id.

0 голосов
/ 12 августа 2009

Один из способов, который мне немного нравится, это создание системы Linq-подобного Object Relational Management (ORM). Где вы можете загрузить структуру таблицы базы данных и манипулировать данными (из таблицы базы данных), как если бы это был просто объект.

т.е.

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

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

, что переводится в следующий SQL:

SELECT `password` from Users;

password в операторе выбора происходит от перегруженного метода.

Результат может быть использован как:

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

Дело в том, что слово "password" может быть заменено любым другим полем в базе данных на лету при программировании.

0 голосов
/ 12 августа 2009

Эта функция на самом деле , что такое объектно-ориентированное программирование , по мнению ее изобретателя Алана Кея: объекты отправляют друг другу сообщения и потенциально реагируют на любые сообщения. Методы, исправленные во время компиляции, являются ограниченной (но также более эффективной) реализацией этой концепции. Вот где известная цитата Кея: «Я изобрел термин« объектно-ориентированный », и я могу вам сказать, что C ++ был не тем, что я имел в виду». приходит от.

По сути, разрешение объектам реагировать на вызовы методов без фиксирования соответствующего метода во время компиляции реализует это оригинальное, более широкое определение ориентации объекта. Большинство современных «динамических» языков поддерживают его в той или иной форме.

Что касается того, для чего это хорошо: посмотрите на Groovy's Builders для хорошего примера. По сути, он позволяет очень компактный синтаксис с низкой избыточностью, превращая сами имена методов в данные.

0 голосов
/ 12 августа 2009

Переадресация сообщений, когда у вас есть составные или агрегированные объекты, где полиморфизм недоступен (скажем, вы используете библиотечный класс, который вы не можете контролировать).

<?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 голосов
/ 12 августа 2009

Вы можете использовать его для случаев, когда класс имеет сложные правила для isset и unset. Например, класс, содержащий переменную $ a, может быть массивом объектов или других ресурсов, и, если он не установлен, они должны выполнять некоторые другие функции.

Хотя я не уверен, почему они позволяют добавлять новое свойство и извлекать не приватное свойство, но вы можете использовать его для изменения внутреннего состояния объекта, вызывая другой код в зависимости от имени свойства / переменная-член устанавливается.

В некоторых случаях это напоминает перегрузку операторов в C ++

0 голосов
/ 12 августа 2009

Другой метод, который Эндрю не упомянул (или не упомянул во время написания), - это избавление от геттеров и сеттеров. Вместо того, чтобы объявлять каждый установщик и получатель следующим образом:

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

Вы можете вместо этого просто сделать

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

Второй метод более естественный.

Магические методы в основном развивают мысль об объектно-ориентированном программировании и идею о том, что то, как вы выполняете работу, не должно иметь значения для внешнего мира. С помощью магических методов он позволяет вам хранить ваши переменные так, как вы хотите, и просто позволять другим классам устанавливать их естественным образом.

Пример: я мог бы хранить все настройки учетной записи моего пользователя в одном массиве, что позволило бы очень легко выполнять итерации, чтобы передать все это до сеанса.

Если бы я не использовал магический метод для этого, мне нужно было бы либо сделать несколько наборов или получить, что означает написание большего количества кода, либо разрешить прямой доступ к массиву, который раскрывает реализацию, поэтому я могу не пойду и поменяю позже.

Вместо этого, используя магические методы, я просто регулярно устанавливаю переменную и работаю с ней внутренне.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...