Объектно-ориентированное программирование, расширяющие свойства - PullRequest
0 голосов
/ 26 июня 2009

Хорошо, это не просто вопрос PHP, но у меня есть эта проблема в PHP, поэтому я опубликую пример на PHP.

Пример:

У меня есть три класса, скажем, data_abstract, человек и студент. Теперь у меня есть один массив данных, связанных с каждым из этих объектов.

class person extends data_abstract
{
    protected $data; //name, gender, etc
}

class student extends person
{
    protected $data; //student_id, etc
}

Теперь, предполагая, что каждое из этих свойств «data» происходит из таблиц базы данных, например, table_person, table_student.

После создания экземпляра мы проанализируем имя класса с помощью функции get_class () и получим данные из связанных с ними таблиц.

class data_abstract
{
    public function __construct()
    {
        $name = get_class($this);
        $table = 'table_' . $name;

       $this->data = DB->query('SELECT * FROM ' . $table); 
       //whatever DB constant is, 
       //I'm just trying to get all rows of data from the related table.
    }
}

Хорошо, теперь проблема, когда я создаю экземпляр студента с помощью $ student = new student (); конструктор получит данные из table_student для меня и поместит их в $ student-> data, но я не смогу получить данные из table_person и поместить эти два набора данных в один объект.

Расширяя другой класс, мы можем расширять и настраивать все методы (функции) (посредством полиморфизма), но расширение атрибутов / свойств каждого уровня объекта кажется трудным, по крайней мере, без какой-либо ручной конструкции.

Есть ли какой-либо способ на уровне абстракции для достижения этого?

(спасибо за чтение, хотел бы я прояснить вопрос.)

Ответы [ 2 ]

3 голосов
/ 26 июня 2009

Если я хорошо понимаю:

  • вы хотите, чтобы все данные вашей БД были в $ data;
  • $ данные должны быть снабжены данными из таблицы 'table_classname';
  • $ data «наследует» от $ data, который должен был быть загружен в родительский класс с этим процессом.

В этом случае вы должны вывести $ data feed, чтобы вы могли перегружать подачу данных. Я отредактировал, теперь у нас есть рабочий пример:

class DataAbstract // Using caps is much better for class name
{
    public function __construct()
    {
        $this->loadData();
    }

    public function loadData()
    {
        // don't use getclass on $this or $this will refer to the children
        $table = 'table_' . __CLASS__; 
        $this->data = array($table); 
    }
}


class Person extends DataAbstract
{

    public function __construct()
    {
        parent::__construct();
    }

    public function loadData()
    {
        parent::loadData();
        $table = 'table_' . __CLASS__;
        $this->data = array_merge($this->data, array($table)); 
    }
}

class Student extends Person
{
    public function __construct()
    {
        parent::__construct();
    }

    public function loadData()
    {
        parent::loadData();
        $table = 'table_' . __CLASS__;
        $this->data = array_merge($this->data, array($table)); 
    }
}

$c = new student();
print_r($c->data);

Выходы

Array
(
    [0] => table_DataAbstract
    [1] => table_Person
    [2] => table_Student
)

Кстати, помните, что PHP получил интроспекцию, он позволяет вам динамически устанавливать нужные поля: может быть, чище, используя большой массив.

Если вы знаете все имена полей, вы можете сделать что-то вроде

function populate($data) // get the array from the DB
{
    $fieldList = get_class_vars($this); // get the filed list

    foreach ($fieldList as $key => $value)
    {
        $this->$key = $data[$key]; // feed the field one by one with the array
    }
}
1 голос
/ 26 июня 2009

Лично я бы поместил класс загрузки базы данных в защищенный метод, который принимает атрибут $tablename и загружает все данные. Затем в конструкторе класса назовите его вручную, а родительский.

class Person 
{
    public function __construct() {
        $this - > loadData("Person");
    }
}

Class Student extends Person 
{
    public function __construct() {
        parent::__construct();
        $this - > loadData("Student");
    }
}

Теперь, когда вы создаете Student, загружаются как данные из Student, так и Person. если вы используете array_merge(), 2 массива данных будут объединены в один.

Это вопрос стиля; некоторые люди будут критиковать это, говоря, что вы теперь повторяете что-то дважды - больше работы по рефакторингу - но я бы сказал, что вы отделяете имена классов и интерфейсы от дизайна базы данных (хорошо), и с помощью родительского вызова код теперь больше ОО.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...