Есть ли способ сказать php complier, что я хочу конкретное неявное преобразование из одного типа в другое?
Простой пример:
class Integer { public $val; } function ExampleFunc(Interger $i){...} ExamFunc(333); // 333 -> Integer object with $val == 333.
[edit] … кто-то попросил пример. Вот пример из 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); }
Длительный ответ:
Я думаю, что очень сложно (для читателей невозможно ) для PHP сделать неявное преобразование в этом случае.
Помните: тот факт, что вы называете свой класс Integer, является подсказкой для человеческого читателя кода, PHP не понимает, что на самом деле он используется для хранения целого числа. Кроме того, тот факт, что он имеет атрибут, называемый $ val, является подсказкой для читателя, который должен содержать значение целого числа. Снова PHP не понимает ваш код, он только выполняет его.
В какой-то момент вашего кода вы должны сделать явное преобразование. Возможно, у PHP есть хороший синтаксический сахар для этого, но первая попытка будет примерно такой:
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 имеет синтаксический сахар, который скроет явное преобразование более или менее.
Укороченная версия:
Так или иначе вам понадобится явное преобразование
PHP5 имеет тип намека, с ограничениями: http://ca2.php.net/manual/en/language.oop5.typehinting.php
Указанные типы должны быть объектами или массивами , поэтому встроенные типы, такие как строка и int , недопустимы.
Это не преобразование, но будет выдавать ошибку, если объект указанного типа не передается методу или функции, как в вашем примере.
На самом деле это возможно с расширением SPL_Type . Он определяет классы для примитивных типов , объекты которых взаимозаменяемы с примитивными типами PHP (booleans, enums, ints, float и strings).
Первый пример будет работать, просто наследуя от SplIt следующим образом:
class Integer extends extends \SplInt{} function ExampleFunc(Interger $i){...} ExamFunc(333); // 333 -> Integer object with $val == 333.
Проблема заключается в том, что код расширения Spltypes не поддерживается с 2012 года, и к моменту этого сообщения он не портирован на PHP 7, и нет такого плана.
ОБНОВЛЕНИЕ Я нашел следующий неофициальный порт типов SPL для PHP 7. Используйте на свой страх и риск: https://github.com/esminis/php_pecl_spl_types
Основные инструкции по установке:
phpize
. ./configure
make && make install
echo "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini
service php7.0-fpm restart
Нет, PHP не является строго типизированным языком.
Вы спрашиваете, как набирать текст? Ты можешь сделать:
$ php -r 'var_dump("333");' string(3) "333" $ php -r 'var_dump((int)"333");' int(333)
В противном случае PHP слабо типизирован, так что вообще вам не нужно это делать. Это подразумевается языком. Например. если функция принимает числовой аргумент, то это число может быть строковым, целочисленным или float все равно; При необходимости значение преобразуется. Вот почему вы можете, например, echo 33
без ошибок.
PHP не строго типизирован.
Вы хотите что-то вроде, всякий раз, когда вы передаете экземпляр hbool в функцию, ожидающую bool, она автоматически конвертируется с использованием вашего неявного конвертера.
Что происходит, так это то, что никакая функция «ожидает» bool, все это динамически типизировано. Вы можете принудительно выполнить явное преобразование, вызвав (int)$something
но если это так, вы можете передать вместо $something->to_otherthing()
вместо неавтоматических преобразований.
PS: Я уверен, что я не понимаю здесь. Я попытаюсь отредактировать этот ответ после того, как я что-нибудь съел 🙂
Этот вопрос очень старый, но я хотел бы дать решение. Это поведение называется бокс, который можно сделать в PHP, но обратный этому, unboxing, см .:
function a(int $a){...} a(new Integer(1));
в настоящее время невозможно. Если вы хотите создать фреймворк, который предлагает вам это и даже больше, посмотрите на BlazeFramework, который имеет такие классы-оболочки.
Операционная перегрузка не работает ни в php. Реализация, возможно, слишком много для написания, но я даю вам подсказку! PHP вызывает набор обратных вызовов с помощью set_error_handler()
с уровнем ошибки E_RECOVERABLE_ERROR
и debug_backtrace()
предоставляет информацию о вызове функции / метода.
Если вы этого не сделаете, посмотрите на реализацию метода blaze\lang\System#systemErrorHandler()
, но, возможно, лучше использовать инфраструктуру, если вы хотите больше таких функций.