php: псевдо абстрактные классы (гложет вопрос)

Модератор: Модераторы разделов

Аватара пользователя
Anguis
Сообщения: 212
ОС: Manjaro 17

php: псевдо абстрактные классы

Сообщение Anguis »

Здравствуйте, уважаемые. Решил я переписать все написанные мной прямолинейные движки с использованием ООП. Т.е. на классах, а не на функциях.
В php пишу уже довольно давно, но так получилось, что ООП пользоваться не доводилось, в основном, потому что плохо понимал принцип работы, а изучить времени не хватало. Но вот выдалась свободная неделька и я решил сесть за ООП. После первых попыток мне очень понравилась гибкость такого подхода, откуда и возникло желание переписать движки.
И вот я столкнулся с такой интересной особенностью, в разборе которой и прошу помощи.

Итак, приступим. Есть абстрактный класс в котором описаны методы которые должны иметь все остальные классы:

Код: Выделить всё

class base{ //базовый класс в котором описаны методы используемые всеми классами
function base(){
die('Невозможно создать объект абстрактного класса!');
}
function attr($name){ //возвращает значение атрибута по его имени
    return $this->$name;
}
function setattr($name,$value){ //устанавливает атрибут по паре имя - значение. Допускается использование массивов.
    if(gettype($name)=='array' and gettype($value)=='array' and sizeof($name)==sizeof($value)){
        $i=0;
        foreach($name as $val){
            $this->$val = $value[$i];
            $i++;
        }
        return true;
    }
    elseif(gettype($name)=='array' and gettype($value)!='array'){
        echo 'Несоответствие заданных типов переменных или размеров массивов при определении аттрибутов!';
        return false;
    }
    else{
        $this->$name = $value;
        return true;
    }
}
}


А еще есть несколько подобных классов:

Код: Выделить всё

class content extends base{//класс, отвечающий за работу с материалами, чтение, добавление, удаление, редактирование.
var $id;
var $img;
var $translit;
var $name;
var $section_id;
var $description;
var $dates;
var $url;
function initiate($tra){
    $res = mysql_query("SELECT `id`,`name`,`section_id`,`img`,`description` FROM `content` WHERE `translit`='$tra'");
    if(mysql_num_rows($res)>0){
        $res=mysql_fetch_array($res);
        $s=new section($res['section_id']);
        $this->setattr(array('id','translit','name','section_id','description','img','url'),array($res['id'],$tra,$res['name'],$res['section_id'],$res['description'],$res['img'],$s->attr('url').$tra.'/'));
    }else{
        unset($this);
        return false;
    }
}
function init_id($i){
    $res = mysql_query("SELECT `translit` FROM `content` WHERE `id`='$i'");
    $this->initiate(mysql_result($res, 0));
}
}


Так вот, при попытке создать объект класса content

Код: Выделить всё

$s=new content;

скрипт почему-то пытается создать объект абстрактного класса base, что естественно приводит к ошибке и остановки работы:
Невозможно создать объект абстрактного класса!


Так-же заметил, что если сделать конструктор внутри класса, т.е. привести к такому виду:

Код: Выделить всё

class content extends base{//класс, отвечающий за работу с материалами, чтение, добавление, удаление, редактирование.
var $id;
var $img;
var $translit;
var $name;
var $section_id;
var $description;
var $dates;
var $url;
function content(){} // !!!--Если добавляю эту строку - работает--!!!
function initiate($tra){
    $res = mysql_query("SELECT `id`,`name`,`section_id`,`img`,`description` FROM `content` WHERE `translit`='$tra'");
    if(mysql_num_rows($res)>0){
        $res=mysql_fetch_array($res);
        $s=new section($res['section_id']);
        $this->setattr(array('id','translit','name','section_id','description','img','url'),array($res['id'],$tra,$res['name'],$res['section_id'],$res['description'],$res['img'],$s->attr('url').$tra.'/'));
    }else{
        unset($this);
        return false;
    }
}
function init_id($i){
    $res = mysql_query("SELECT `translit` FROM `content` WHERE `id`='$i'");
    $this->initiate(mysql_result($res, 0));
}
}
, то ошибка исчезает и скрипт отрабатывает отлично.

Я в недоумении почему так. Может кто-то объяснить?
Спасибо сказали:
Аватара пользователя
deadhead
Сообщения: 1913
Статус: zzz..z

Re: php: псевдо абстрактные классы

Сообщение deadhead »

В первом случае при создании content требуется конструктор этого класса, если его нет, то конструктор, по возможности, ищется вверх по иерархии. То как именно будет искаться не найденный метод (конструктор) в случае множественного наследования определяется порядком разрешения метода.
[x] close
Спасибо сказали:
Аватара пользователя
Anguis
Сообщения: 212
ОС: Manjaro 17

Re: php: псевдо абстрактные классы

Сообщение Anguis »

deadhead писал(а):
30.04.2010 17:58
В первом случае при создании content требуется конструктор этого класса, если его нет, то конструктор, по возможности, ищется вверх по иерархии. То как именно будет искаться не найденный метод (конструктор) в случае множественного наследования определяется порядком разрешения метода.


А почему конструктор нужен в обязательном порядке?
Что-то не могу найти инвы о порядке разрешения методов в php... Можно чуть подробнее?
Спасибо сказали:
Аватара пользователя
serzh-z
Бывший модератор
Сообщения: 8259
Статус: Маньяк
ОС: Arch, Fedora, Ubuntu

Re: php: псевдо абстрактные классы

Сообщение serzh-z »

Anguis писал(а):
30.04.2010 19:19
А почему конструктор нужен в обязательном порядке?
Принципы ООП.

Если конструктора нет, то он будет создан компилятором/интерпретатором автоматически.

Anguis писал(а):
30.04.2010 19:19
Что-то не могу найти инвы о порядке разрешения методов в php... Можно чуть подробнее?
Как и в любом (наверное) другом языке: сначала производный класс, затем, если не найдено, смотрим базовый.

Вообще в PHP >= 5 есть волшебный метод __construct(). Использование функии с именем класса, в качесте конструктора, - устаревший подход.

Anguis писал(а):
30.04.2010 17:33
function base(){
die('Невозможно создать объект абстрактного класса!');
}
Вместо die логично было бы использовать throw.

Как правильно решить задачу:

Код: Выделить всё

<?php

abstract class base {
    function __construct() {
        throw new Exception('Please override __construct');
    }
}

class derived extends base {
    function __construct() {
        echo "HELLO;]\n";
    }
}

$a = new derived();
$b = new base();

QUOTE писал(а):php a.php
HELLO ;]
PHP Fatal error: Cannot instantiate abstract class base in E:\a.php on line 16



base::__construct() вызван лишь в том случае, если он не перегружен в производном классе.
Спасибо сказали:
Аватара пользователя
KiWi
Бывший модератор
Сообщения: 2521
Статус: статус, статус, статус

Re: php: псевдо абстрактные классы

Сообщение KiWi »

Anguis писал(а):
30.04.2010 17:33

Код: Выделить всё

function attr($name){ //возвращает значение атрибута по его имени
...
}
function setattr($name,$value){ //устанавливает атрибут по паре имя - значение. Допускается использование массивов.
...
}

И это -- тоже достаточно спорное решение. В ООП есть Overloading. В данном случае -- __get, __set.
Спасибо сказали:
Аватара пользователя
iljaCPP
Сообщения: 48
ОС: Slackware

Re: php: псевдо абстрактные классы

Сообщение iljaCPP »

Anguis , не надо путать перекрытие, переопределение, и перегрузку.
Это разные термины с разными последствиями.
Спасибо сказали: