Как навсегда типизировать свойства класса в PHP? - PullRequest
0 голосов
/ 18 января 2020

Я читал раздел «Видимость» руководства PHP , и в первом комментарии кто-то упоминает:

ВНЕШНИЙ КОД может привести свойства элемента к любые другие PHP типы (логические, целые числа, числа с плавающей запятой, строки, массивы и объекты и т. д. c.) - еще одна огромная ошибка.

Рассмотрим пример:

class base {
    public $foo = 1;
}

$first = new base();

(string)$first->foo; //I thought just this expression would typecast
var_dump($first->foo); //but I found it still is int


$first->foo = (string)$first->foo;    
var_dump($first->foo); //ok so public props can be typecasted

Только из-за защищенных и закрытых свойств мы не можем изменить их тип извне? Или это относится и к свойствам publi c?

Ответы [ 3 ]

8 голосов
/ 18 января 2020

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

Приведение типов не влияет на исходную переменную или значение. Создает новое значение типа Typecasted, которое необходимо назначить, если вы хотите сохранить.

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

Это абсолютно ничего не делает для $string:

$string = "123";
(int)$string;

... и приведенное значение типа теряется, поскольку мы не присваиваем результат операции

С помощью следующего мы можем перезаписать значение $class::$someInteger, если выполняется пара условий:

$class->someInteger = (string) 123;
  1. Что свойство является public c. (Очевидно, вы не можете получить прямой доступ к свойствам private или protected извне класса. Вы можете обмануть это, используя рефлексию или такие странные вещи, как использование метода получения, который возвращает ссылку свойству, но оба являются очень плохими идеями для производственного кода).
  2. Вы не используете PHP 7.4 типизированные свойства и объявили тип для него.

«Постоянная» часть вопроса особенно ошибочна, поскольку в PHP обычно переменные не имеют типов .

Вы можете присвоить значения любого типа любой переменной. И когда у них действительно есть типы (PHP 7.4 типизированные свойства), нет никакого практического способа изменить определенный тип (опять же, может быть способом, использующим отражение ... но я не пойду туда ).

2 голосов
/ 22 января 2020

Ваш вопрос основан на неправильном понимании значения термина Typecasting. Страница PHP Руководства по приведению типов и всего руководства в целом неадекватна и является не автономный канонический справочник для изучения языка php. Кроме того, предполагается, что вы владеете другими языками программирования, такими как C.

Typecasting не определяется как преобразование типа данных переменной; это преобразование типа данных выражения - В общем, это в большинстве языков программирования. Wikipedea определяет его следующим образом:

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

Официальное руководство использует три термина, а именно: жонглирование типов , преобразование типов и приведение типов, Из первого абзаца можно догадаться, что жонглирование типов и преобразование типов - это одно и то же. В первом абзаце говорится:

Обратите внимание, что это не меняет типы самих операндов; единственное изменение заключается в том, как оцениваются операнды ...

Должно быть ясно, что жонглирование типов определенно не меняет тип переменная. Из руководства php это выглядит как жонглирование типа и приведение типа - это две разные концепции. Вопрос в том, что поскольку Руководство PHP никогда не определяет эти термины , как мы можем убедиться, что эти два термина совпадают и что они на самом деле означают. В статье Type Casting руководство гласит:

Приведение типов в PHP работает так же, как и в C: ...

Итак, ответ таков: можно смело предположить, что определение приведение типов из языка C применимо к языку PHP. В C языке приведение типов определяется так же, как определение в Википедии, то есть преобразуется только тип данных выражения. Следующие выдержки взяты из книги C Язык программирования от K & R, 2-е издание , раздел 2.7, стр. 45:

В конструкции (type-name) expression, выражение преобразуется в именованный тип ... ... Точное значение приведено так, как если бы выражение было присвоено переменной указанного типа c ... ... мы можем использовать sqrt((double) n) ... ... Обратите внимание, что приведение производит значение n в соответствующем типе, само n не изменяется.

Это завершает тот факт, что приведение типов в php работает так же, как жонглирование типов в том смысле, что тип данных переменных (операндов), с которыми выполняются действия, не изменяется. Вы можете использовать функцию settype() для преобразования типа данных переменной.

Как указано в первом абзаце, страница руководства php по типам дает следующий технически неверный комментарий в их последнем абзаце:

Чтобы принудительно преобразовать переменную в определенный тип , либо приведите переменную, либо используйте для нее функцию settype ().

Теперь вы знаете, что на самом деле означает приведение типа в php и почему у вас было это заблуждение, было бы лучше перефразировать ваш вопрос следующим образом:

Перефразированный вопрос: Как окончательно преобразовать тип данных свойств класса в PHP.

Должно быть очевидно, что свойства publi c будут легко преобразованы в другой тип с помощью settype($myObj->myPubProp, required-type). Интересно, что вопреки предложению, сделанному в исходном ответе пользователя yivi, свойства , privated и protected могут быть оценены и их тип может быть преобразован извне класса [ 1 ] [ 2 ].

Метод 1: Использование ссылок:

class myClass {
    private $prop = 786; //Could be protected too.    

    public function &assess_priv(){
        return $this->prop;        
    }
    public function display_prop() {
        echo var_dump($this->prop);
    } 
}

$obj = new myClass;
$newObjProp = &$obj->assess_priv();
settype($newObjProp, "string");
$obj->display_prop(); //converted the data type of private property of a class  

Метод 2: Использование PHP перегрузка свойства

error_reporting(E_ALL);

class myClass {
    private $prop = 786; //Could be protected too.    

    public function __set($name, $value)
    {
        $this->$name = $value;
    }

    public function __get($name)
    {
        return $this->$name;
    } 
}

$obj = new myClass;
var_dump($obj->prop);
$obj->prop = (string)$obj->prop; //Interestingly, settype($obj->prop, "string"); can't be used
echo "</br>";
var_dump($obj->prop); //converted the data type of private property of a class  
0 голосов
/ 29 января 2020

Тип свойств класса приведения теперь доступен в php7.4.

<?php
class User {
    public int $id;
    public string $name;
}
$user = new User;
$user->id = 123; // this will work
$user->id = "hello world"; // throws fatal error

Неустранимая ошибка : Uncaught TypeError: Типизированное свойство User :: $ id должно быть int, строка используется в [...] [...]: 7 Трассировка стека: # 0 {main} добавляется в [...] [...] on line 7

Вам необходимо переключиться на php7.4. Эта функция теперь доступна в 7.4 ссылке на их официальные документы

Это ссылка в песочнице , чтобы попробовать онлайн.

...