面向对象的编程,扩展属性

时间:2009-06-26 07:08:00

标签: php oop

好的,这不仅仅是一个PHP问题,但我在PHP中遇到了这个问题,所以我将在PHP中发布这个例子。

示例:

我有三个课程,比如data_abstract,person和student。现在,我有一个与每个对象相关的数据数组。

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->数据中,但是我将无法从table_person获取数据并将这两组数据放入一个对象中。

通过扩展另一个类,我们可以扩展和定制所有方法(函数)(通过多态),但扩展每个对象级别的属性/属性似乎很难,至少没有一些手动构建。

抽象级别有没有办法实现这个目标?

(感谢阅读,希望我能让问题更清楚。)

2 个答案:

答案 0 :(得分:3)

如果我理解得很好:

  • 您希望$ data中的所有数据库数据;
  • $ 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 :(得分:1)

就个人而言,我会将数据库加载类放在一个受保护的方法中,该方法接受属性$tablename,并加载所有数据。然后在类的构造函数中手动调用它,以及父类。

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

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

现在,当您构建Student时,StudentPerson的数据都会被加载。如果使用array_merge(),则2个数据阵列将合并为一个。

这是风格问题;一些人会批评这一点,说你现在重复两次 - 更多的工作重构 - 但我会说你正在将类名和接口与数据库设计脱钩(一件好事)和父调用,代码是现在更多的是OO。