Вопрос по types, php – Неявное преобразование типов для классов PHP?

1

Есть ли способ сообщить компилятору 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);
        }
конкретный неявный, разве это не будет явным? Malfist
ты не смешиваешь понятия здесь? Я не знаю C #, но кажется, что код, на который вы ссылаетесь, создает оператор для преобразования из одного типа в другой, но в php это происходит автоматически, вам не нужно создавать способ преобразования, скажем, из строки в int .. Carlos Lima
на самом деле, нет. Явное, когда вы делаете что-то вроде: ExamFunc ((Integer) 333) в C # у вас есть неявный оператор: class MyType {открытый статический неявный оператор int (MyType m) {// код для преобразования из MyType в int}} Msdn.microsoft.com / EN-US / библиотека / z5z9kes2 (VS.71) .aspx Will Shaver

Ваш Ответ

6   ответов
2

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

Я думаю, это очень сложно (читайневозможн) для 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 есть синтаксический сахар, который более или менее скрывает явное преобразование.

Укороченная версия

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

Думаю, я спрашиваю, что это за "синтаксический сахар". Я использовал и нравится в C # и искал что-то похожее в PHP. Может быть, здесь не повезло. Will Shaver
Я добавил пример c #. Will Shaver
Хотите показать тот же пример в коде C #? Мне интересно и возможно это дает подсказку, как добиться того же эффекта php5 dwergkees
Я подумал, что ваш вопрос похож на Java ... класс Java Integer имеет специальную ссылку на тип примитива, который, насколько я знаю, не может быть воспроизведен пользовательским кодом (хотя я далеко не эксперт по Java) , Проблема в том, что у PHP нет такой ссылки. Я думаю, что лучшее, что вы можете сделать, это обернуть проверку типов и преобразование в другую функцию, чтобы ее можно было многократно использовать, и ваш ExampleFunc () может просто вызвать toIntegerObj ($ i) в качестве первой строки; не заботясь о том, что было передано, и зная, что теперь у него есть объект Integer. gapple
3

http: //ca2.php.net/manual/en/language.oop5.typehinting.ph

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

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

1

SPL_Type extension. Он определяет классы для примитивные типы чьи объекты работают взаимозаменяемо с примитивными типами PHP (логические значения, перечисления, целые числа, числа с плавающей запятой и строки).

Первый пример будет работать, просто наследуя от 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_type

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

Клоновый код:https: //github.com/esminis/php_pecl_spl_types.gi Генерировать @ Настрои файл. Внутри директории кода введите:phpize. Создать файл make:./configure Скомпилируйте код и установите:make && make install Добавьте модуль в конфигурацию PHP. В Ubuntu введитеecho "extension=spl_types.so" > /etc/php7/conf.d/spl_types.ini Перезапустите PHP-FPM (если используете его):service php7.0-fpm restart
0

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

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

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

0

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

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

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

0

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

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

a(new Integer(1));

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

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

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

Похожие вопросы