PHP 类定义
不看一些代码就很难讨论对象;因此,让我们深入并展示如何编写类定义的示例,然后从类中实例化一个对象。
在 PHP 中,一个类如下所示:
class facts_about_the_world { private $population_growth_rate, $shape, $base_year; public $population_base; public function __construct() { $this->shape = 'Somewhat round anyway...'; //Note. The Population growth rate is not exponential, since it may vary from year to year //Therefor, this can only be used to calculate a rough estimate.. $this->population_growth_rate = 1.0105; $this->population_base = 7594000000; //(2016 estimate) $this->base_year = 2016; } public function get_shape() { return $this->population_base; } public function set_shape($value) { $this->population_base = $value; return true; } public function population_by_year(int $year) { if ($year < $this->base_year) { echo 'It is not possible to go backwards in time.'; exit(); } $n = $year-$this->base_year; //PHP uses "**" for exponentation instead of caret "^" //See: https://onitroad.com/exponential-growth-php return $this->population_base*$this->population_growth_rate**$n; } }
这是一个非常简单的类,可以显示有关我们世界的各种事实,还可以估计给定年份的未来世界人口。
要从这个类实例化一个对象,我们可以这样做:
$earth = new facts_about_the_world();
然后,为了调用属于该类的公共方法,我们可以这样做:
echo $earth->population_by_year(2050);
如果一个属性被声明为 public,我们也可以直接从外部访问它:
echo $earth->population_base;
但是,通常不建议直接访问这样的属性,因为它也允许我们修改属性; PHP 仍然没有只读关键字,因此我们将不得不使用 getter 和 setter 来安全地操作对象数据。
对象是从它们对应的类定义实例化的实体;一般来说,一个设计良好的类应该与其依赖项松散耦合,而不是对需要使用该类的作者隐藏它们。
对象实际上只是类的实例化版本,因此,类定义本身可能比实例化对象更有趣。
当使用类型声明时,我们也可以指向一个对象的类定义作为类型;这样做将使函数或者方法只接受给定“类定义”的对象作为参数——这是防止作者意外传递不正确依赖项的有用方法。
getter 和 setter
由于将属性声明为 public 可能会产生不需要的副作用,我们应该改为将它们声明为私有,然后创建 getter 和 setter 来帮助我们访问私有属性。
PHP 也有魔法方法 __get 和 __set ,当直接访问属性时会调用它们;但是我们可能仍然想创建我们自己的 getter 和 setter,因为它更灵活。
Facts_about_the_world PHP 类还有一个名为 $shape 的私有属性,要访问该属性,我们必须使用 get_shape 方法;现在,这是一个非常基本的方法,因为它只返回 $shape 属性的值:
echo $earth->get_shape(); //Returns: Somewhat round anyway...
现在,要更改私有 $shape 属性的值,我们应该使用我们专门为此目的定义的方法:
echo $earth->set_shape('The Earth is completely flat...');
对象方法和属性
此类中的方法(也称为函数)被声明为公共;当从类实例化对象时,会自动调用 __construct 方法;这也被称为一种神奇的方法。
也可以在方法内部定义函数,但不推荐这样做。
魔术方法必须声明为公共方法才能工作。
也可以将方法声明为 private ,这样做的效果是该方法只能在类本身内调用。
属性是一种变量类型,是类定义的一部分;也可以在各个方法中使用局部变量;但是,必须使用 $this->property_name 调用属性。
使用属性的优点是它们可以被类中的所有方法访问,而不必将它们作为参数传递。