使用 main class 的现有值实例化 subclass php

Instantiation of subclass php with existing values of the main class

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

我是 OOP 的新手,发现它很有用,但又感到困惑。

我看过了,我认为这一定是一个简单的问题,但搜索了 "instantiation of subclass php" 之类的东西,但没有找到任何要点。

我想实例化一个对象,然后再实例化子对象class。我可以 "add" subclass 到现有实例吗?

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?

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

现在是凌晨 3 点 30 分,如果这真的很愚蠢,我深表歉意,但最近几天我碰壁了,落后了。这似乎对当前项目有用。

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

第二天有人说 "that dog is a beagle"(好的,在文件的后面 - 这不是一个很好的例子)所以我们想用名字 Suki 实例化一个 Beagle class。

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

再次抱歉。去睡觉了。

一般解法:(如果你已经知道未来的子class)

只需直接创建子实例class。您可以将它用作 superclass 的实例。但是,有关您要实现的目标的更多信息会很有用。

所以它会像这样工作:

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");

如您所见,无需再次将父 class 的方法添加到子 class。它们将被隐式继承,您可以只在 subclasses 的实例上使用它们,就好像它们是在 subclass.

中定义的一样

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

具体解决方案:(以防不知道实际的subclass)

如果您不能直接创建子class,请像这样创建一个构造函数:

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");

我没有测试代码,所以可能仍然存在错误,但它应该能理解我的观点。

Parent 和 child classes
您可以创建 2 个 class,让我们调用一个 ParentClass 和一个 ChildClass。这给了我们:

class ParentClass
{
}

class ChildClass
{
}

如您所见,它们没有以任何方式、形状或形式链接,因此,我们需要 扩展 child class 到使用 parent,所以我们现在有:

class ParentClass
{
}

class ChildClass extends ParentClass
{
}

现在 child 与 parent 对话,所以让我们在 parent 中添加一个 属性,我们称之为 name:

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

class ChildClass extends ParentClass
{
}

现在让我们为 child、getter 和 setter 添加一些功能:

class ParentClass
{
    protected $name;
}

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

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

如您所见,它使用 parent 中的 $name,这意味着它的值可用于 child,因此我们可以:

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

并得到结果!

编辑
额外显示 setters 中的差异:

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;
    }
}

正如您在这个例子中看到的,有 2 个 child class,BeagleDalmatian,每个 setter 都有些不同对于值。

由于 parent class 中的值不是静态的,它们在每个 child 中都会不同,因此设置一个不会改变另一个,反之亦然。

要在所有子 class 中保留 parent 的值,请使用静态属性:

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};