使用主类的现有值实例化子类php

时间:2016-02-01 13:41:06

标签: php class subclass instantiation

编辑:真的很抱歉搞砸了原来的例子。最后有更多解释。

我是OOP的新手,发现它有用,发现它令人困惑。

我看了,我认为这必须是一个简单的问题,但搜索了“子类php的实例化”之类的东西,但却找不到任何关键点。

我想实例化一个对象,然后再实例化子类。我可以将子类“添加”到现有实例吗?

class Dog
{
    protected $owner;
    protected $color;

    public function setOwner($owner)
    {
        $this->owner = $owner;
    }
    public function setColor($color)
    {
        $this->color = $color;
    }
}

class Bulldog extends Dog
{
    protected $name;
    protected $typeOfTail;

... set tail....
    public function setName($name)
    {
        $this->name = $name;
    }
}

class Beagle extends Dog
{
    protected $name;
    protected $typeOfSpots;

... set spots ....
    public function setName($name)
    {
        $this->name = $name;
    }
}


$myDog = new Dog;
$myDog -> setOwner("Bob");

$myDog1 = new Beagle;
$myDog1 -> setName("name");

显然这不起作用,但如果我这样做

$myDog = new Beagle;
$myDog -> setName("name");

我认为只是将所有者设置为NULL?

有没有办法将类的现有值(或复制值)拉入子类的实例(我想我可以做一些复杂的方法来提取所有的值,但是有很多这些值....)这在PHP中很容易做到,还是我在LIMB上做了?

现在是凌晨3点30分,如果这真的很愚蠢,我会道歉,但是最近几天我遇到了障碍,而且我落后了。这似乎在当前项目中可能有用。

澄清:这是一个假设的例子。 (没有狗参与该项目。)假设我们有一只由Fred拥有的棕色狗,我们填充了dog的一个实例(假装它是一个有很多进展的大班)。

第二天有人说“那条狗是比格犬”(稍后在文件中确定 - 这不是一个很好的例子)所以我们想要实例化一个名为Suki的Beagle类。

我想要的是Beagle的实例,它继承了已存在的 dog信息。

再次抱歉。去睡觉了。

2 个答案:

答案 0 :(得分:0)

一般解决方案:(如果您已经知道未来的子类)

直接创建子类的实例。您可以将它用作超类的实例。但是,有关您正在尝试实现的更多信息将非常有用。

所以它会像这样工作:

class Dog
{
    protected $owner;
    protected $color;

    public function setOwner($owner)
    {
        $this->owner = $owner;
    }
    public function setColor($color)
    {
        $this->color = $color;
    }
}

class Beagle extends Dog
{
    protected $name;

    public function setName($name)
    {
        $this->name = $name;
    }
}


$myDog = new Beagle;

// here we call two methods of the Dog superclass
$myDog->setOwner("Bob");
$myDog->setColor("brown");

// now we call a method of the subclass
$myDog->setName("SomeName");

正如您所看到的,不需要再次将父类的方法添加到子类中。它们将被隐式继承,您可以在子类的实例上使用它们,就好像它们是在子类中定义一样。

如果省略其中一个方法调用,则属性将为null,因为没有为属性分配默认值。

具体解决方案:(如果您不知道实际的子类)

如果无法直接创建子类,请创建如下构造函数:

class Dog
{
    protected $owner;
    protected $color;

    public function __construct(Dog $dog = null) {
        if ($dog) {
            foreach ($dog as $key => $value) {
                if (property_exists($this, $key)) {
                    $this->{$key} = $value;
                }
            }
        }
    }

    public function setOwner($owner)
    {
        $this->owner = $owner;
    }
    public function setColor($color)
    {
        $this->color = $color;
    }
}

class Beagle extends Dog
{
    protected $name;

    public function setName($name)
    {
        $this->name = $name;
    }
}

$dog = new Dog;
$dog->setOwner("Bob");

$beagle = new Beagle($dog);
$beagle->setColor("brown");

我没有测试代码,所以也许它还有一个bug,但它应该得到我的观点。

答案 1 :(得分:0)

家长和班级
您可以创建2个类,我们可以调用一个ParentClass和一个ChildClass。这给了我们:

class ParentClass
{
}

class ChildClass
{
}

如您所见,它们没有以任何方式,形状或形式链接,因此,我们需要扩展子类以使用父类,所以我们现在有:

class ParentClass
{
}

class ChildClass extends ParentClass
{
}

现在,孩子与父母交谈,所以让我们为父母添加一个属性,让我们称之为name

class ParentClass
{
    protected $name; //Protected means it's private, but accessible to children
}

class ChildClass extends ParentClass
{
}

现在让我们为孩子添加一些功能,一个getter和一个setter:

class ParentClass
{
    protected $name;
}

class ChildClass extends ParentClass
{
    public function setName($value)
    {
        $this->name = $value;
    }

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

正如您所看到的,它使用了来自父级的$name,这意味着孩子可以使用它的值,所以我们可以这样做:

$childClass = new ChildClass();
$childClass->setName("My Name");
print $childClass->getName(); // prints My Name

得到一个结果!

修改
额外显示二传手的区别:

class Dog
{
    protected $owner;
    protected $color;
    protected $name; // I'd put this here as all dogs have a name, right?

    // Put the getters in here as all they do is return, they won't change (hopefully...)
    public function getOwner()
    {
        return $this->owner;
    }
    public function getColor()
    {
        return $this->color;
    }
    public function getName()
    {
        return $this->name;
    }
}

class Beagle extends Dog
{
    public function setOwner($val) 
    {
        $this->owner = $val;
    }
    public function setColor($val)
    {
        $this->color = $val;
    }
    public function setName($val)
    {
        $this->name = $val;
    }
}

/**
 * Added extra code to setters
 */
class Dalmatian extends Dog
{
    public function setOwner($val)
    {
        $this->owner = "Owner: " . $val;
    }
    public function setColor($val)
    {
        $this->color = "Color: " . $val;
    }
    public function setName($val)
    {
        $this->name = "Name: " . $val;
    }
}

正如您在此示例中所看到的,有两个子类BeagleDalmatian,每个子类的值都有一些不同的设置器。

由于父类中的值不是静态的,因此每个子节点的值都不同,因此设置一个不会改变另一个,反之亦然。

要在所有子类中保留父级的值,请使用静态属性:

class Dog
{
    protected static $owner;
    protected static $color; // Don't know why you'd want this kept, but okay?
}

使用static::${variable_name};拨打电话,而不是:$this->{variable_name};