[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: type casting
Dezigo
Не знаю ,где тему создать, пускай будет в этой ветке , хочу обсудить неудобства php.
Самая больная тема это визуальное представление типа, то есть ,знать какой тип имеет аргумент.
Из за этого простого не сходства php, скрипты трудно debug делать.
Я накатал простой пример и тут уже возникает великая проблема.
Начнём всё порядку.
Простое бинарное дерево с приминением объектов.

index.php
<?php

error_reporting(E_ALL);
ini_set('display_errors', TRUE);
ini_set('display_startup_errors', TRUE);

include 'TreeBuilder.php';
include 'Node.php';

function console($message, $value = null) {
if (is_null($value))
echo $message . '<br/>';
else
echo $message . ': --> ' . $value . '<br/>';
}

console('Start');
try {
$run = new TreeBuilder();
$run->add(5);
$run->add(3);
$run->add(1);
$run->add(4);
$run->add(10);
} catch (Exception $e) {
console($e->getMessage());
}
console('End');
?>


TreeBuilder.php
<?php

/**
* Description of TreeBuilder
*
*
@author dezigo
*/

class TreeBuilder {

private $root = null;

private function insert($value, $node) {
if (is_null($this->root)) {
$this->root = new Node($value);
console('Root added', $value);
return;
}

//left
if ($node->value > $value) {
if (is_null($node->left)) {
$node->left = new Node($value);
console('Node left ' . $node->value, $value);
} else {
$this->insert($value, $node->left);
}
}

//right
else {
if (is_null($node->right)) {
$node->left = new Node($value);
console('Node right ' . $node->value, $value);
} else {
$this->insert($value, $node->right);
}
}
}


public function add($value) {
if (!is_int($value)) {
throw new Exception("Failed to add $value,a value supports only int type");
}
$this->insert($value, $this->root);
}
}


Node.php
<?php

class
Node {
public $left;
public $right;
public $value;

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


  • 1. Если вбить тип аргумента для value
    add((int) $value)

    И подать $run->add(5);
    Вилетит ошибка, что тип должен быть именно int, а не integer.
    И тогда опять неудобства, нужно делать проверки типа.
  • 2. Какого типа node ?
     private function insert($value, $node) 

    Если я напишу
    private function insert($value,Node $node) 

    И запущу свой скрипт, то вилетит ошибка, которая скажет ,что тип требуется тип от Node,вы подали Null - давай досвидания!
    Опять делаем проверки на экземпляр.
  • 3. Пример с __callstatic

      
    public static function __callstatic($method, $args) {
    return (object) call_user_func_array(array(self::$instance[self::$driver], $method), $args);
    }

    Какого типа возврат объекта?
    Просто object, правельно.
    Теперь сделаем
    Работаем с этим объектом, php не видит его - по Type Hinting
    Что можно в jave
    (DB)((object)this.getDb()).type_hitting_it_works

    а php этого не позволяет.
    (DB)((object)$this->getDb())->type_hitting_it_works

    Ужастно не удобно :(
  • 4.
    С первого взгляда какого типа ?

    public $left;
    public $right;


    Ответ, да хз
    Нету возможносту
    public Node $left;
    public Node $right;

    А руки так и чешутся это добавить..
    Так просто рассуждение, что раздражает именно в php,а именно не жёсткая типизация., а отсутствие альтернативы ( хочешь ставь , хочешь не ставь)





Спустя 44 минуты, 29 секунд (5.10.2012 - 12:03) -=CASPER=- написал(а):
Как альтернативу можно использовать phpDOC к методам и свойствам класса. По крайней мере любая нормальная IDE распознает описание к эллементу класса.

Цитата
Если я напишу
private function insert($value,Node $node)

Всё правльно, ошибку выдаст потому что у тебя
private $root = null;

а в методе add() ты передаёшь это свойство как второй аргумент к методу insert().

У тебя слишком много лишних, ненужных проверок в классе.

Спустя 8 минут, 57 секунд (5.10.2012 - 12:12) Dezigo написал(а):
Хорошо
    private $root;

Какого типа root?
Я же не могу написать вот так
    private Node $root;

Цитата
У тебя слишком много лишних, ненужных проверок в классе.

Я Вас не понял. Аргументируйте Ваш ответ.
"Слишком много"
У меня одна проверка, и то для примера.
if (!is_int($value))

Спустя 26 минут, 27 секунд (5.10.2012 - 12:38) -=CASPER=- написал(а):
private $root;

По умолчанию будет иметь тип NULL и относится к классу TreeBuilder.
Если бы ты записал в него ссылку на экземпляр класса Node тогда он имел бы тип данных object.
Как минимум класс будет:
class TreeBuilder {

private function insert($value, Node $node) {
//left
if ($node->value > $value) {
if (is_null($node->left)) {
$node->left = new Node($value);
console('Node left ' . $node->value, $value);
} else {
$this->insert($value, $node->left);
}
}

//right
else {
if (is_null($node->right)) {
$node->left = new Node($value);
console('Node right ' . $node->value, $value);
} else {
$this->insert($value, $node->right);
}
}
}


public function add($value) {
if (!is_int($value)) {
throw new Exception("Failed to add $value,value support only int types");
}

$this->insert($value, new Node($value));
}
}

По сути мне ещё не очень нравится метод insert(), никак толком не пойму что ты в нём хочешь сделать.

Спустя 14 минут, 27 секунд (5.10.2012 - 12:52) Dezigo написал(а):
Вы проверяли свой пример?


 $this->insert($value, new Node($value));

Вы каждый раз создаёте новый объект. Это не правельно.
И поэтому ответ
Start
Node right 5: --> 5
Node right 3: --> 3
Node right 1: --> 1
Node right 4: --> 4
Node right 10: --> 10
End


Два метода 1 публичный, а другой приватный.
insert - потому что как бы пользователь не имеет доступ к root корню.
Пользователь должен просто указывать значение и не думать.


Спустя 2 минуты, 48 секунд (5.10.2012 - 12:55) Dezigo написал(а):
Забыл добавить.
Результат..
Start
Root added: --> 5
Node left 5: --> 3
Node left 3: --> 1
Node right 3: --> 4
Node right 5: --> 10
End

Спустя 6 минут, 44 секунды (5.10.2012 - 13:02) Dezigo написал(а):
Цитата
По умолчанию будет иметь тип NULL и относится к классу TreeBuilder.

Согласен, тип Object я могу написать, и какие мне это даст преимущества?
Type casting всё равно не работает, да и я не могу написать
(node)$node->left;



Цитата
phpDOC

Согласен, а как насчёт

public static function __callstatic($method, $args) {
return (object) call_user_func_array(array(self::$instance[self::$driver], $method), $args);
}


Что мне писать в phpDOC, чтобы у меня сработал type hinting?
Возврат известен, что объект, но какой?

Спустя 5 минут, 7 секунд (5.10.2012 - 13:07) Dezigo написал(а):
Пример из android.

Ищем по id и указываем тип возврата.
И впомощь нам от java идёт type hinting
(Button) findViewById(R.id.EnterButton).объект от button->
(EditText) findViewById(R.id.test).объект от EditText

Спустя 35 секунд (5.10.2012 - 13:08) Oyeme написал(а):
-=CASPER=-
Ваш пример неверен и он жутко привязывает логику.Это в корне это неверный подход. wink.gif

Спустя 9 минут, 47 секунд (5.10.2012 - 13:17) -=CASPER=- написал(а):
Dezigo, для того чтобы явно узнать какому классу принадлежит тот или иной эллемент достаточно использовать опператор instanceof.
Например:
class MyClass {}

$a = new MyClass;
var_dump($a instanceof MyClass);

Выведет bool (true) потому что переменная $a принадлежит классу MyClass.

Спустя 12 минут, 57 секунд (5.10.2012 - 13:30) Dezigo написал(а):
Да,
Цитата
instanceof
, это ещё одна проверка.. Всё верно.
Но это не как не помогает type hinting. Каждый раз надо проверять является ли объект данным типом.

Всем известен пример в codeIgniter
загружаем класс
$model = $this->load->model('Model_name');


Какого типа $model? ;)
Известно, но type hinting у ней нету, поэтому для того чтобы обратиться к методам данного объекта $model->.. надо открыть сам файл модели, и скопировать(написать самому ручками) этот метод.. иначе ведь не как.
И в этом классе опять типа таково
$model->user->getSettings()->..здесь какой нить объект, который всё портит и приходиться лезть в эти файлы и делать var_dump(), а лучше вывести список методов через natvia reflections class :(
http://php.net/manual/en/class.reflectionclass.php

Спустя 7 минут, 45 секунд (5.10.2012 - 13:38) Guest написал(а):
Это холивар на тему строгой типизации на уровне разработчиков.
Большинство программистов против этого в PHP. Поэтому разрабы PHP не спешат к строгости, иначе бы уже язык достиг бы строгой типизации. Хотя я за строгую, это помогает лучше создавать код.

Спустя 7 минут, 35 секунд (5.10.2012 - 13:46) Guest написал(а):
Цитата
Всем известен пример в codeIgniter
загружаем класс
$model = $this->load->model('Model_name');
Какого типа $model? ;)


Угу, тот же самый проблем в YII с загрузкой модуля.
Хотелось бы что бы на уровне IDE было проинтегрировано. Например phpStorm вроде интегрировали YII, но всё равно эту конструкцию никак не понимает
$testModule =Yii::app()->getModule('test');
$var = $testModule->getVars(); // Здесь уже метод не видим

Спустя 8 минут, 23 секунды (5.10.2012 - 13:54) Dezigo написал(а):
Да.. согласен с вами.. просто обидно и если читать книгу на php, то можно просто запутаться, те же примере шабонов ООП, очень нагладно показываются в java , c#, потом просто переписываешь это на php..

Спустя 3 минуты, 18 секунд (5.10.2012 - 13:57) -=CASPER=- написал(а):
Цитата (Oyeme @ 5.10.2012 - 10:08)
-=CASPER=-
Ваш пример неверен и он жутко привязывает логику.Это в корне это неверный подход.  ;)

После того как увидел то что выводит код всё стало на свои места :)
Вот как я исправил код:
Класс Node остался неизменным:
class Node {

public $left;
public $right;
public $value;

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

}

Класс TreeBuilder:
class TreeBuilder {

/**
* Ссылка на объект
*
*
@var \Node
*/

private $root;

/**
* Конструктор
*
*
@param int $value
*/

public function __construct($value) {
$this->isInt($value);
$this->root = new Node($value);

console('Root added', $value);
}

/**
* Проверка на число
*
*
@param int $value
*
@throws Exception
*/

private function isInt($value) {
if (!is_int($value)) {
throw new Exception("Failed to add $value,value support only int types");
}
}


/**
* Вывод
*
*
@param int $value
*
@param Node $node
*/

private function insert($value, Node &$node) {
if($node->value > $value) {
// left
if($node->left === NULL) {
$node->left = new Node($value);
console('Node left '.$node->value, $value);
} else {
$this->insert($value, $node->left);
}

}
else {
// right
if($node->right === NULL) {
$node->right = new Node($value);
console('Node right '.$node->value, $value);
} else {
$this->insert($value, $node->right);
}
}
}


/**
* Запись
*
*
@param int $value
*/

public function add($value) {
$this->isInt($value);
$this->insert($value, $this->root);
}
}

Собственно сам вывод:
function console($message, $value = NULL) {
if ($value === NULL)
echo $message . '<br/>';
else
echo $message . ': --> ' . $value . '<br/>';
}

#-----------#

console('Start');
try {
$run = new TreeBuilder(5);
$run->add(3);
$run->add(1);
$run->add(4);
$run->add(10);
} catch (Exception $e) {
console($e->getMessage());
}
console('End');

Спустя 53 секунды (5.10.2012 - 13:58) -=CASPER=- написал(а):
Результат:
Start
Root added: --> 5
Node left 5: --> 3
Node left 3: --> 1
Node right 3: --> 4
Node right 5: --> 10
End

Спустя 8 минут, 16 секунд (5.10.2012 - 14:07) Dezigo написал(а):
-=CASPER=-
Ваша хитрость это конструктор.
    public function __construct($value) {
$this->isInt($value);
$this->root = new Node($value);

console('Root added', $value);
}


Остроумнно :D , вы всего лишь обошли эту проблему ))
  $this->root = new Node($value);


5. Ещё один косяк в php это приравнивание в свойствах.
Почему я не могу написать вот так?

private $root = new Node(); //создадим объект
private Node $root; //объявим тип

Ни одно из этих способов не работают :(

Спустя 6 минут, 16 секунд (5.10.2012 - 14:13) -=CASPER=- написал(а):
Dezigo, потому что PHP это язык не со строгой типизацией. Можно даже сказать с плавающими типами данных smile.gif В процессе кода типы данных могут меняться. Взять те же данные полученные методом POST или GET. Все они будут иметь тип string, без разницы какое бы значение им было бы передано.
То же самое с данными из БД (насколько мне память не изменяет smile.gif ).
Просто смеритесь с этим. Это не косяк ЯП, это его особенность wink.gif

Спустя 5 минут, 19 секунд (5.10.2012 - 14:18) Dezigo написал(а):
-=CASPER=- Кстате ссылка сдесь не нужна, только потому что, все объекты и так передаються по ссылке. ;)
private function insert($value, Node &$node) { .. }


Ну может в php 6 решат эти проблемы. ))))

Спустя 30 секунд (5.10.2012 - 14:19) Guest написал(а):
Цитата
5. Ещё один косяк в php это приравнивание в свойствах.
Почему я не могу написать вот так?


private $root = new Node(); //создадим объект
private Node $root; //объявим тип


Ни одно из этих способов не работают sad.gif

Ну это скорее всего не косяк, а правильно заложенная логика.
Инициализация должна быть в определённом месте: в java это анонимный блок может быть, в PHP конструктор, в RUBY метод initialize (кстати RUBY строго допускает инициализацию только в методе initialize). Это более читаемо чем делать какие то действия в блоке определения свойств.
Ну а типизация свойства опять же холивар, PHP не строго типизированный язык и свойство может изменяться, этим и "вкусности" проявляются его (так многие разработчики заявляют)

Спустя 8 минут, 11 секунд (5.10.2012 - 14:27) -=CASPER=- написал(а):
Цитата (Dezigo @ 5.10.2012 - 11:18)
-=CASPER=- Кстате ссылка сдесь не нужна, только потому что, все объекты и так передаються по ссылке.  ;)
private function insert($value, Node &$node) { .. }

Ну да, чтот я запарил, но явное указание передачи по ссылке погоду не испортит :)
Можно просто убрать 1-ин символ (&), если он мозолит глаза, вот и всё :)

Спустя 11 часов, 36 минут, 8 секунд (6.10.2012 - 02:03) Invis1ble написал(а):
это и достоинство и, одновременно, недостаток php

PS. Лично меня бы порадовала жесткая типизация.

Спустя 36 минут, 11 секунд (6.10.2012 - 02:39) inpost написал(а):
Invis1ble
В 95% случаев тебе не надо париться над типом переменной. А остальные 5% - укажи вручную, если надо.

Спустя 5 часов, 31 минута, 17 секунд (6.10.2012 - 08:10) Invis1ble написал(а):
inpost
спасибо, я в курсе smile.gif

Спустя 3 часа, 20 минут, 21 секунда (6.10.2012 - 11:31) inpost написал(а):
Invis1ble
Где плюсик в карму?

Спустя 1 день, 23 часа, 45 минут, 53 секунды (8.10.2012 - 11:17) Dezigo написал(а):
inpost
Какой смысл от кармы ? wink.gif

Спустя 19 минут, 6 секунд (8.10.2012 - 11:36) inpost написал(а):
Dezigo
Это стёб! Не вижу смысла уже давно smile.gif

Спустя 8 минут, 7 секунд (8.10.2012 - 11:44) Игорь_Vasinsky написал(а):
потом на гривны или рубли обмениваются. по курсу.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.