PHP 继承:面向对象编程的基石

admin 2024-03-07 613 阅读 0评论

你是否曾仔细观察过自己,发现身上流淌着父母血脉的某些特质?对我而言,我明显继承了母亲的一些特性。尽管此刻我并不打算详细列举,但这与接下来的讨论息息相关。

今天要共同探讨一个主题——继承。在面向对象编程的世界里,继承是一个核心概念,而今天,将用 PHP 为媒介,带大家一同探寻其内在的逻辑与魅力。

正如我们所知,继承是面向对象编程的基石之一。原则,简而言之,就是为某一事物提供指导的法则。因此,当我们说继承是面向对象编程的原则时,我们其实是在强调它作为一种指导原则,为面向对象编程提供了基础和支持。

那么,这个所谓的继承原则究竟是何方神圣?简而言之,继承允许子类从父类中继承属性和方法。这里有两个核心概念需要我们理解——“子类”和“父类”。

你是否还记得我们开篇时的讨论?我提到了自己遗传了母亲的一些特质。这,其实正是继承的精髓所在。

继承赋予了子类从父类中继承方法和属性的能力。为了更好地理解,让我们通过一段简单的代码示例来揭示其工作原理。在这段代码中,我将使用“父亲”和“儿子”的关系,为大家呈现继承是如何在实际编程中运作的。

首先,我们定义一个“父亲”类。

<?php

class Father
{
    public string $name = "Father";

    public function allBusinesses(): string{
        return "All Businesses” . PHP_EOL;
    }

    public function allProperties(): string{
        return "
All Properties". PHP_EOL;
    }
}

在上述代码中,我们可以清晰地看到父类的结构。它拥有一个用于存储父亲姓名的属性,并且定义了两个方法:allBusinesses 和 allProperties。在这个上下文中,这个父类将充当我们继承体系中的基类。它不仅为我们提供了共享的属性,还定义了一系列的方法,这些方法将在后续的派生类中得到继承和应用。接下来,我们将继续探讨关于这个父类的更多细节和它在整个继承体系中的作用。

<?php

class Son extends Father
{

}

这是第二个类,名为Son类。如您所见,Son类目前是空的,不包含任何代码实现。但我希望您注意一些重要的细节。在Son类声明中,您注意到了extends关键字吗?我相信您已经注意到了。这个关键字在我们希望从另一个类(称为父类或超类)继承属性和方法时使用。在这种情况下,我们使Son类继承了Parent类。

现在我们已经创建了Son类,并通过extends关键字从Parent类继承了属性和方法,那么接下来我们应该做什么呢?

首先,我们需要理解在扩展父类时后台发生了什么。每当一个子类扩展一个父类时,该子类会自动获得父类的所有公共(public)和受保护(protected)属性和方法的访问权限。

因此,在我们的例子中,Son类将能够访问Parent类的所有公共和受保护属性和方法。为了验证这一点,我们可以进行一些简单的测试。例如,我们可以为Parent类添加一些公共方法,然后在Son类的对象上调用这些方法,看看是否可以正常工作。同样,我们也可以尝试在Son类中添加新的方法,以展示子类可以扩展父类的功能。

<?php

require_once 'Father.php';
require_once 'Son.php';

$son = new Son();

print $son->allProperties();
print $son->allBusinesses();

通过上面的代码,您能够清晰地观察到我们是如何通过实例化该类来创建一个新的Son对象。进一步地,您也会注意到,我们正在调用父类上的AllpropertiesallBusinesses方法。现在,让我们一同来探索一下执行这些操作后所得到的结果。

All Properties
All Businesses

因此,你能够清晰地看到我们已经得出了准确的结果。正如在现实生活中,我们从亲生父母那里继承了属性和业务一样,我们也能够从父类成功地继承 allProperties 和 allBusinesses 方法。请务必记住,我们的 Son 类并未定义任何自己的方法。它完全依赖于并从 Father 类中继承了所有的方法。让我们再次回顾一下。

<?php

class Son extends Father
{

}

我确信,经过之前的探讨,您已对面向对象编程(OOP)中的核心概念——继承,有了深刻的理解。继承机制允许子类从其父类中继承属性和方法,这一特性赋予了子类利用父类已有代码的能力。

继承的一大优势在于提高了代码的可重用性。通过继承,我们可以避免代码的重复编写,提高编程效率。这意味着,一旦我们在父类中定义了某个方法或属性,子类就可以直接使用,而无需在子类中重新编写相同的代码。以税收计算为例,我们可以更清晰地理解这一点。

设想一下,我们正在开发一款税收计算软件,该软件需要处理政府工作人员和私人工作人员的税收问题。在这种情况下,假设这两种类型的工人缴纳相同比例的税,即10%。如果我们不使用继承,那么我们可能需要为每种工人类型分别编写计算税收的代码。但是,通过使用继承,我们可以创建一个通用的“Worker”类,其中包含计算税收的方法,然后让政府工作人员和私人工作人员类继承自这个“Worker”类。这样,我们就可以避免在多个地方重复编写相同的代码,提高了代码的复用性。接下来,让我们通过代码示例来具体展示这一概念。

<?php

class GovernmentWorker
{
    public string $name;

    public int $salary = 10000;

    public function calculateTax(): int
    {
        return $this->salary * 10 /100;
    }
}

在这里,我们向您展示一个政府工作人员类。这个类详细地列出了其属性和方法,以便您更好地了解它的功能和特性。紧接着,我们还将为您呈现一个私人工人班的相关内容。

<?php

class PrivateWorker
{
    public string $name;

    public int $salary = 9000;

    public function calculateTax(): int
    {
        return $this->salary * 10 /100;
    }
}

如您所见,私有工作者类同样具备自己的属性和方法。我们可以计算上述各类别的税费,一切似乎井然有序。然而,存在一个棘手的问题。您可能正纳闷这是什么问题?其实,问题在于代码的重复性。您会发现,在GovernmentWorkerPrivateWorker类中,存在名为calculateTax的方法。这个方法在两个类中执行的功能完全相同,都是使用相同的逻辑来计算税收。

我们需要寻找一种方式,将calculateTax方法集中在一个地方,并通过继承来复用它。而不是每次需要时都在各个类中复制这个方法。设想一下,如果我们还需要为另外100种需要计算税收的工人添加这个方法,那么每次都复制并粘贴calculateTax方法显然不是一个明智的选择。我们正在努力避免的就是这种代码的重复性。

那么,让我们共同探索解决问题的策略。实际上,我已经有了一个解决方案。我们可以将需要在程序多个部分使用的calculateTax方法放入一个基类中。这样,每当我们需要计算税收时,只需从基类中继承这个方法即可。现在,让我们深入了解一下这个方案。

<?php

class Worker
{
    public function calculateTax(): int
    {
        return $this->salary * 10 /100;
    }

}

在我们上面所提到的 Worker 类中,您可能已经注意到,我已经精心地为其添加了一个名为 CalculateTax 的方法。这样,无论何时我们需要利用这个方法,我们只需对 Worker 类进行扩展,并通过继承来轻松获取该方法的功能。通过这种方式,我们确保了代码的模块化和可重用性,使得代码更加清晰、易于维护。

<?php

require_once 'Worker.php';
class GovernmentWorker extends Worker
{
    public string $name;

    public int $salary = 10000;
}

之前,我们已对Worker类进行了扩展,通过继承CalculateTax方法,现在我们可以方便地调用此方法来执行相关计算了。以下是一个示例:

<?php


require_once 'GovernmentWorker.php';

$governmentWorker = new GovernmentWorker();
$tax = $governmentWorker->calculateTax();

print $tax;

请问您是否愿意欣赏一下我们如何利用继承的CalculateTax方法来实现税款的精准计算呢?

请看下面的结果。

1000

现在,我们已经具备了计算政府工作人员税收的能力。紧接着,我们将运用同样的方法,来计算私人工人的税收。为了实现这一目标,我们将从 Base Worker 类中继承该方法,并随后将其付诸实践。

<?php

require_once 'Worker.php';

class PrivateWorker extends Worker
{
    public  $name;

    public int $salary = 9000;

}

现在,我们将采用此方法对私人工人的税收进行计算。

<?php


require_once 'PrivateWorker.php';

$privateWorker = new PrivateWorker();
$tax = $privateWorker->calculateTax();

print $tax;

结果

900

我们刚刚展示了继承的一个显著优势,那就是代码重用。代码重用不仅帮助我们避免冗余的代码编写,还使我们的代码更加清晰和整洁。

现在,我想与您分享的是,当子类从父类继承属性和方法时,它们有权对这些继承的内容进行调整或重写,以满足其特定的需求。

让我们用一个生动的例子来解释这一点。假设你从父母那里继承了一家企业。当你开始接手经营时,你可能会发现一些可以改进的地方,于是你引入了自己的创新理念,按照自己的方式重新塑造了这家企业。

这正是面向对象编程中继承的魅力所在。子类具有修改和重写从父类继承的方法和属性的能力。

现在,让我们回到我们的税收计算软件示例。您可能还记得,PrivateWorkerGovernmentWorker类都是从ParentWorker类继承了calculateTax方法。这个方法原本是将税款计算为工资的10%。但假设政府后来决定将税率降低到5%。这时,我们面临一个问题:我们继承自基类的calculateTax方法仍然按照10%的税率来计算税款。

那么,我们该如何解决这个问题呢?如何确保政府工作人员的税率现在是5%,而不是10%?答案其实很简单。我们之前提到过,子类可以重写从父类继承的方法和属性。

因此,我们只需在GovernmentWorker类中重新定义一个名为calculateTax的方法,并在这个新方法中设置税率为5%。这样,当我们为政府工作人员计算税款时,就会使用新的税率。

下面,我将通过代码示例来演示这一过程。

<?php

require_once 'Worker.php';
class GovernmentWorker extends Worker
{
    public string $name;

    public int $salary = 10000;

    public function calculateTax(): int
    {
        return $this->salary * 5 /100;
    }

}

从上面的代码中,我们可以看到在“政府类”中声明了一个名为calculateTax的方法。这正是我们打算修改的子类。此次修改意味着计算的税率将为5%。可能您会好奇,为什么要这样做呢?让我为您解释。

请注意,我们当前是在扩展“Worker”基类(也就是父类),并从其中继承了calculateTax方法。继承的方法原本是按照10%的税率来计算税收的。但是,对于我们的“政府类”而言,并不希望使用这样的税率。根据最新的政府政策,我们希望税率调整为5%。

为了实现这一点,我们在子类中重写了从父类继承来的calculateTax方法,并以符合新政策的方式实现了它。现在,当我们计算税金时,税率将是5%。而私人工人的税率则仍然保持为10%。

请牢记,我们是在“政府类”上重写了calculateTax方法。

接下来,让我们来测试一下我们的代码,以确保一切按预期工作。

<?php


require_once 'GovernmentWorker.php';


$governmentWorker = new GovernmentWorker();
$tax = $governmentWorker->calculateTax();

print $tax;

经过我们的修改,所得到的结果将不再是1000,即10000的10%,而是现在的500。这是因为我们重新编写了继承的方法,并在子类(政府类)中按照自己的逻辑实现了这个方法。下面请查看我们的修改结果:

500

我恳请您理解并重视这样一点:在重写子类上的方法时,确保新方法与所继承的方法具有相同的名称是至关重要的。正如您之前所观察到的,我们在重写政府类(子类)上的calculateTax方法时,特意保持了与父类方法相同的命名,以确保正确的覆盖和继承机制得以实施。这种一致性不仅有助于代码的清晰性和可维护性,还能确保程序在运行时能够正确地调用相应的方法,从而实现预期的功能。

喜欢就支持以下吧
点赞 0

发表评论

快捷回复: 表情:
aoman baiyan bishi bizui cahan ciya dabing daku deyi doge fadai fanu fendou ganga guzhang haixiu hanxiao zuohengheng zhuakuang zhouma zhemo zhayanjian zaijian yun youhengheng yiwen yinxian xu xieyanxiao xiaoku xiaojiujie xia wunai wozuimei weixiao weiqu tuosai tu touxiao tiaopi shui se saorao qiudale qinqin qiaoda piezui penxue nanguo liulei liuhan lenghan leiben kun kuaikule ku koubi kelian keai jingya jingxi jingkong jie huaixiao haqian aini OK qiang quantou shengli woshou gouyin baoquan aixin bangbangtang xiaoyanger xigua hexie pijiu lanqiu juhua hecai haobang caidao baojin chi dan kulou shuai shouqiang yangtuo youling
提交
评论列表 (有 0 条评论, 613人围观)