【问题标题】:How to access child class variables from parent class如何从父类访问子类变量
【发布时间】:2014-09-08 19:55:13
【问题描述】:

我有以下类继承的情况:

class Entity
{
  public $db; //connection

  ...
}

CustomerProduct 类扩展 Entity 类:

class Customer extends Entity
{
   public $cname;
   public $cdesc;

   private function populate($row)
   {
     foreach($row as $key=>$val) $this->$key=$val;
   }

   public function fetch()
   {
     $sql="SELECT cname,cdesc FROM customers";
     $rst=$this->db->query($sql);
     $row=$rst->fetch_assoc();
     $this->populate($row);
   }
}

class Product extends Entity
{
   public $pname;
   public $pdesc;

   private function populate($row)
   {
     foreach($row as $key=>$val) $this->$key=$val;
   }

   public function fetch()
   {
     $sql="SELECT pname,pdesc FROM products";
     $rst=$this->db->query($sql);
     $row=$rst->fetch_assoc();
     $this->populate($row);
   }
}

从这里可以看出,每个子类都有相同的函数populate($row),它从子类获取数据库行并填充相应类的变量;此函数自动填充变量:$this->cname=$row['cname']、$this->cdesc=$row['cdesc'] 等(看我的另一篇帖子here)。

现在我想将此函数从子类拉到父类 Entity 并由所有子类继承,但有一个问题。 $this->$key=$val 这个函数动态填充(尝试填充)父类变量,我想填充子类变量。如何定义该函数填充子类变量? (我想在这里有类似 child::$key=$val 但 child:: 不存在的东西)。

【问题讨论】:

  • 您在这里使用的是 object 变量,而不是 class 变量(在 php 中由 static 表示),并且没有子/父对象的关系。
  • 在 Programmers 上发现重复:programmers.stackexchange.com/questions/151910/… - 摘录:不可能。
  • 确实,我在这里使用对象变量而不是(静态和所有子共享的)类变量。问题仍然存在,如何在父类中定义一个会改变其子类变量的函数。
  • @sbrbot:是的,但是没有“子”或“父”对象之类的东西。只有类可以是“孩子”或“父母”。
  • 你正在做的工作。您始终可以按名称修改变量。

标签: php oop inheritance


【解决方案1】:

也许我遗漏了一些东西,但你可以让函数受保护,然后在子类中访问它:

class Entity
{
    protected  $db; //connection

    protected  function populate($row)
    {
        foreach($row as $key=>$val) $this->$key=$val;
    }
}


class Customer extends Entity
{
    public $cname;
    public $cdesc;

    public function fetch()
    {
        $sql="SELECT cname,cdesc FROM customers";
        $rst=$this->db->query($sql);
        $row=$rst->fetch_assoc();
        $this->populate($row);
    }
}

class Product extends Entity
{
    public $pname;
    public $pdesc;

    public function fetch()
    {
        $sql="SELECT pname,pdesc FROM products";
        $rst=$this->db->query($sql);
        $row=$rst->fetch_assoc();
        $this->populate($row);
    }
}

【讨论】:

  • 是的,你错过了这个,问题是父类的 populate() 函数中的“$this->”。 $this-> 应该引用子对象的 $this->
  • @sbrbot 你能否做一个活生生的例子(codepad.viper-7.com 或类似的)来显示我的代码失败并且你的工作,因为我无法弄清楚你所说的子对象是什么意思(我不相信那里是这样的),我现在真的很好奇
  • 抱歉 user574632 回复晚了,我测试了它,它按预期工作。令人惊讶的是,您在此处发布的内容是我在这一切开始时所做的,并且在调用我的函数并将其更改为第二种方法时出现了一些错误。但似乎问题出在其他问题上。但是,您的帖子让我重新测试了这件事,现在有了更好的代码。如果你对我的第一个(不是最好的)反应有点不高兴,那很好,我可能会以同样的方式做出反应。感谢您为帮助我所做的努力。
  • @sbrbot 一点也不沮丧,只是好奇。很高兴你把它整理好,很高兴我能帮上忙。
【解决方案2】:

如果您试图仅通过关系从另一个产品访问有关一个产品的特定数据,那么您将无法做到。

如果您想从父级访问子级数据,那么我建议您创建一个接口,该接口定义了获取所需数据的标准化方法:

interface EntityInterface
{
    public function getName();
    public function getDescription();
}

那么你的 Product 只定义了方法...

class Product extends Entity implements EntityInterface
{
    public $pname;

    public function getName() {
        return $this->pName;
    }
}

您的顶级实体类使用这些访问器:

class Entity
{
    public function printName() {
        echo $this->getName();
    }
}

【讨论】:

    【解决方案3】:

    这就是Abstract classes 的用途。您在父类中定义您想要的内容,然后您的孩子实现它。或多或少,这就是乔所描述的,只是融入了一个方便的类

    abstract class Entity
    {
        // Note that we're defining this here and not in the child 
        // so we're guaranteed this is set
        /* @var string */
        public $pName;
    
        public function printName() {
            echo $this->getName();
        }
    
        abstract public function getName($name);
    }
    
    class Product extends Entity
    {
        //Note that, just like an interface, this has to implement it just like the parent
        public function getName($name) {
            return $this->pName;
        }
    }
    

    【讨论】:

    • 谢谢@Machavity,我很清楚抽象类是什么,这里的问题是函数形式父类应该填充不是这个父类($this)而是子类的变量,并且该函数必须从哪些子变量中知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-08-15
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多