2009-06-30 4 views
1

Есть ли способ сказать php complier, что я хочу конкретное неявное преобразование из одного типа в другое?Неявное преобразование типов для классов PHP?

Простой пример:

class Integer 
{ 
    public $val; 
} 

function ExampleFunc(Interger $i){...} 

ExamFunc(333); // 333 -> Integer object with $val == 333. 

[править] ... кто-то спросил для примера. Вот пример из C#. Это логический тип, который меняет значение после его обращения один раз.

/// <summary> 
    /// A Heisenberg style boolean that changes after it has been read. Defaults to false. 
    /// </summary> 
    public class hbool 
    { 
     private bool value; 
     private bool changed = false; 

     public hbool() 
     { 
      value = false; 
     } 

     public hbool(bool value) 
     { 
      this.value = value; 
     } 

     public static implicit operator bool(hbool item) 
     { 
      return item.Value; 
     } 

     public static implicit operator hbool(bool item) 
     { 
      return new hbool(item); 
     } 

     public bool Value 
     { 
      get 
      { 
       if (!changed) 
       { 
        value = !value; 
        changed = true; 
        return !value; 
       } 
       return value; 
      } 
     } 

     public void TouchValue() 
     { 
      bool value1 = Value; 
     } 

     public static hbool False 
     { 
      get { return new hbool(); } 
     } 

     public static hbool True 
     { 
      get { return new hbool(true); } 
     } 
    } 

     [Test] 
     public void hboolShouldChangeAfterRead() 
     { 
      hbool b = false; 
      Assert.IsFalse(b); 
      Assert.IsTrue(b); 
      Assert.IsTrue(b); 
      hbool b1 = false; 
      Assert.IsFalse(b1); 
      Assert.IsTrue(b1); 
      Assert.IsTrue(b1); 
      hbool b2 = true; 
      Assert.IsTrue(b2); 
      Assert.IsFalse(b2); 
      Assert.IsFalse(b2); 
      bool b3 = new hbool(); 
      Assert.IsFalse(b3); 
      Assert.IsFalse(b3); 
      Assert.IsFalse(b3); 
     } 
+0

конкретные неявное, не было бы явным? – Malfist

+0

нет действительно. Явное, когда вы делаете что-то вроде: ExamFunc ((Integer) 333) в C# у вас есть неявный оператор: класса MyType { общественный статический неявный оператор INT (MyType м) { // код для преобразования от MyType к Int }} http://msdn.microsoft.com/en-us/library/z5z9kes2(VS.71).aspx –

+0

вы не смешивая понятия здесь? Я не знаю C#, но кажется, что код, на который вы ссылаетесь, создает оператор для преобразования из одного типа в другой, но он автоматически в php, вам не нужно создавать способ преобразования, скажем, из строки в int .. –

ответ

2

Длинный ответ:

Я думаю, что это очень трудно (читай невозможно) для PHP, чтобы сделать неявное преобразование в этом случае.

Помните: тот факт, что вы называете свой класс Integer, является подсказкой для человеческого читателя кода, PHP не понимает, что он фактически используется для хранения целого числа. Кроме того, тот факт, что он имеет атрибут, называемый $ val, является подсказкой для читателя, который должен содержать значение целого числа. Снова PHP не понимает ваш код, он только выполняет его.

В какой-то момент вашего кода вы должны сделать явное преобразование. Это может быть возможно, что PHP имеет некоторый хороший syntactig сахар для этого, но первая попытка будет что-то вроде:

class Integer 
{ 
    public $val; 

    function __construct($val) { $this->val = $val; } 
} 

function ExampleFunc($i){ 
    if (is_numeric($i)) { $iObj = new Integer($i); } 
    ... 
} 

ExamFunc(333); // 333 -> Integer object with $val === 333. 

Это не так круто, как вы хотели бы, но опять же, вполне возможно, что PHP имеет некоторый синтаксический сахар, который скроет явное преобразование более или менее.

Короткая версия:

Так или иначе, вам потребуется явное преобразование

+0

Наверное, я прошу, что такое «синтаксический сахар». Я использовал и люблю его в C# и искал что-то подобное в PHP. Здесь может быть не повезло. –

+0

Учтите показать тот же пример в коде C#? Я заинтересован и, может быть, это дает нам подсказку о том, как достичь такого же эффекта php5 – dwergkees

+0

Я понял, что ваш вопрос был похож на Java ... класс Java Integer имеет специальную ссылку на примитивный тип, который, насколько я знаю, может 't реплицироваться по коду пользователя (хотя я далек от эксперта по Java). Проблема в том, что PHP не имеет такой ссылки, как в первую очередь. Я думаю, что лучшее, что вы можете сделать, это обернуть проверку и преобразование типов в другую функцию, чтобы она была повторно использована, и ваш ExampleFunc() может просто вызвать toIntegerObj ($ i) в качестве первой строки; не заботясь о том, что он передал, и зная, что теперь он имеет объект Integer. – gapple

0

Нет, PHP не является строго типизированным языком.

3

PHP5 имеет тип намекая, с ограничениями: http://ca2.php.net/manual/en/language.oop5.typehinting.php

Указанные типы должны быть объекты или массив, поэтому встроенные типы, такие как строки и INT не допускаются.

Это не преобразование, но приведет к ошибке, если объект указанного типа не передан методу или функции, как в вашем примере.

0

Вы спрашиваете, как тип актеров? Вы можете сделать:

$ php -r 'var_dump("333");' 
string(3) "333" 
$ php -r 'var_dump((int)"333");' 
int(333) 

В противном случае PHP является слабо типизированным, поэтому в общем случае вам не нужно делать это. Это подразумевается языком. Например. если функция принимает числовой аргумент, то это число может быть строковым, целочисленным или float все равно; При необходимости значение преобразуется. Вот почему вы можете, например, echo 33 без ошибок.

0

PHP не является строго типизированным.

Вы хотите что-то вроде, всякий раз, когда вы передаете экземпляр hbool в функцию, ожидающую bool, она автоматически конвертируется с использованием вашего неявного конвертера.

Что происходит, так это то, что никакая функция «ожидает» bool, все это динамически типизировано. Вы можете принудительно выполнить явное преобразование, вызвав (int)$something, но если это так, вы можете передать $something->to_otherthing() вместо неавтоматических преобразований.

PS: Я уверен, что им не ясно. Я попытаюсь отредактировать этот ответ после того, как я что-нибудь съел :)

0

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

function a(int $a){...} 

a(new Integer(1)); 

не представляется возможным в настоящее время. Если вы хотите создать фреймворк, который предлагает вам это и даже больше, посмотрите на BlazeFramework, который имеет такие классы-оболочки.

Операция перегрузки не работает ни в php. Реализация, возможно, слишком много для написания, но я даю вам подсказку! PHP вызывает обратный вызов с set_error_handler() с уровнем ошибки E_RECOVERABLE_ERROR и debug_backtrace() предоставляет информацию о вызове функции/метода.

Если вы этого не понимаете, посмотрите на реализацию метода blaze\lang\System#systemErrorHandler(), но, возможно, лучше использовать фреймворк, если вы хотите больше таких функций.

1

Фактически это возможно с SPL_Type extension. Он определяет классы для примитивных типов, объекты которых взаимозаменяемы с примитивными типами PHP (булевы, перечисления, ints, float и strings).

Вы первый пример будет работать, просто унаследовав от распределятся следующим образом:

class Integer extends extends \SplInt{} 

function ExampleFunc(Interger $i){...} 

ExamFunc(333); // 333 -> Integer object with $val == 333. 

Проблема заключается в том, что code of the SplTypes extension не поддерживается с 2012 года, и к моменту этого поста, он не имеет портирован на PHP 7, и нет такого плана.

UPDATE Я нашел следующий unnofficial порт Типы SPL на PHP 7. Используйте на свой страх и риск: https://github.com/esminis/php_pecl_spl_types

Основные инструкции по установке:

  1. Clone код: https://github.com/esminis/php_pecl_spl_types.git
  2. Сгенерируйте файл . Внутри каталога кода введите: phpize.
  3. Сформировать сделать файл: ./configure
  4. код скомпилировать и установить: make && make install
  5. Добавить модуль в РНР configuraiton.В Ubuntu, тип echo "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini
  6. Перезапустите PHP-FPM (если использовать его): service php7.0-fpm restart