柔和回答, 使怒消退。言语暴戾, 触动怒气
——箴言篇 15:1
翻译/Lemon黄
来源/https://www.startutorial.com/homes/oo_beginner
1
类(Class) vs 对象(Object)
类就像你家的房子建造时的蓝图。在你的房子被建造之前,有一个房子的蓝图。它不是一栋真正的房子,而是一个构思房子建造起来要是什么样的,要有多少个房间等等的规划。然后,房子才根据这份蓝图来建造。通过这个例子的比对中,我们把房子的蓝图叫做类,实际建造起来的房子称为对象。有一份蓝图,我们可以建造出无限地同样的房子。同理,我们拥有一个类,就可以创建出无限地对象。
关于类和对象,我们需要记住以下几点:
2
PHP 中的类(Class)
类由属性和方法组成。
以下是一个PHP 中的类。在这个简单的类中,$postCode 是类的属性,ringBell() 是类中的方法。注意,他们都用可见性关键词(public)来修饰。
Class House {
public $postCode = “560121”;
public function ringBell() {
echo “Ding Dang Dong”;
}
}
要实例化类的对象,需要使用关键字(new),如下所示:
$house = new House();
3
可见性
没一个属性和方法都有它自己的可见性。PHP中有三种可见性。他们分别是关键词public、protected 和 private。用着三个关键词来控制属性和方法如何被外界访问。
继承:
继承,允许子类继承父类的特性。子类可以继承父类的哪些特性,取决于父类对自身属性和方法的可见性声明。父类中被声明为private的属性/方法,子类无法继承。
class Shape {
public function name() {
echo "I am a shape";
}
}
class Circle extends Shape {
}
$circle = new Circle();
$circle->name(); // I am a shape
继承使用的关键词是 extends 。当 Circle 类 继承 Shape 类时,它可以继承Shape中公共的(public修饰)和受保护的(protected修饰)属性和方法。
4
多态性
为不同类型的实体提供单一接口。基本的意思就是,PHP能够根据数据类型或类,用不同的方式来处理对象。这个强大的特性,允许我们编写共享同一接口的可互换对象。
interface Shape {
public function name();
}
class Circle implements Shape {
public function name() {
echo "I am a circle";
}
}
class Triangle implements Shape {
public function name() {
echo "I am a triangle";
}
}
function test(Shape $shape) {
$shape->name();
}
test(new Circle()); // I am a circle
test(new Triangle()); // I am a triangle
上面的示例中,test(Shape $shape)函数声明(类型提示)其唯一参数为Shape 类型。这个函数中的参数类型,我们就无法确定是 Circle 类型还是 Triangle 类型。由于两个类都继承于 Shape 类,当他们任意中一个作为参数传递给test()函数时,它会各自调用相应类中的方法。
5
封装
封装用于隐藏类中结构化数据对象的值或状态,防止未经授权就能直接访问类中值或状态。这是一个激励我们思考方法/类如何合理隐藏其内部实现/细节的概念。当需要修改的时候,只要自己内本修改就行,而不会影响到系统其它部分的使用。可见性是封装的实现机制。
class Person {
private $name;
public function setName($name) {
$this->name = $name;
}
public function getName($name) {
return $this->name;
}
}
$robin = new Person();
$robin->setName('Robin');
$robin->getName();
在以上简单的类中,字段 $name 被 声明为 私有的(private)。使用这个类的用户不知道 $name 是符合存储在 Persion 类中。现在$name被存储在内存中,我们可以修改Persion类的内部代码,将$name存储到文件中或者数据库中。使用这个类的用户不需要改变内核代码,实际使用这个类的用户也不知道 $name 是怎么被存储的,通过private修饰,$name 被封装起来,并隐藏起来了。
6
抽象化
抽象是将焦点从事物的细节和具体实现转移到事物的类型(即类)、可用的操作(即方法)等,从而使编程更简单、更一般和更抽象的概念。它就像是一个泛化而不是一个规范。
class TV {
private $isOn = false;
public function turnOn() {
$this->isOn = true;
}
public function turnOff() {
$this->isOn = false;
}
}
$tv = new TV();
$tv->turnOn();
$tv->turnOff();
以上代码定义了以 TV类。我们除了把它打开和关闭外,就没什么办法。TV类就是对真实的TV的一个抽象化的简单例子。
7
接口 vs 抽象类
接口,声明类必须具有哪些方法而无需实现它们。实现接口的任何类都必须实现这些声明方法的详细信息。接口不是类,因此不能实例化接口。当需要强制某些类执行某些操作时,它是很有用的。
interface Vehicle {
public function startEngine();
}
class Car implements Vehicle {
public function startEngine() {
echo "Engine Started";
}
}
Vehicle 是一个只声明了 startEngine()方法的接口,Car 实现(实现使用关键字 implements) Vehicle, 所以类 Car 必须实现startengine()方法的功能。
抽象类(使用 abstract 关键字声明)能够强制子类实现类似于接口的方法。当方法在抽象类中声明为抽象时,其子类必须实现该方法。
抽象类与接口有很大的不同。抽象类中可以拥有非抽象的属性和方法,因而抽象类实际上是一个类,所以抽象类是可以被实例化为对象。
abstract class Vehicle {
abstract public function startEngine();
public function stopEngine() {
echo "Engine stoped";
}
}
class Car extends Vehicle {
public function startEngine() {
echo "Engine Started";
}
}
Vehicle 是一个抽象类,Car 继承 Vehicle ,所以Car必须实现startEngine()方法的功能,因为startEngine()方法被声明为抽象的。但是 Car 不需要去实现stopEngine()方法的功能,stopEngine()是一个普通的方法,可以被子类继承使用。