【翻译】PHP面向对象的基本概念

生活哲言

柔和回答, 使怒消退。言语暴戾, 触动怒气

——箴言篇 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。用着三个关键词来控制属性和方法如何被外界访问。

  • public:允许外界的任何人来访问类中的属性和方法。当一个属性或者方法没有使用可见性关键词来修饰时,默认的是 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()是一个普通的方法,可以被子类继承使用。

原文发布于微信公众号 - Lemon黄(lemonhunag)

原文发表时间:2019-09-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券