PHP 面向对象
面向对象编程的三个主要特性:
- 封装(Encapsulation):指将对象的属性和方法封装在一起,使得外部无法直接访问和修改对象的内部状态。通过使用访问控制修饰符(public、private、protected)来限制属性和方法的访问权限,从而实现封装。
- 继承(Inheritance):指可以创建一个新的类,该类继承了父类的属性和方法,并且可以添加自己的属性和方法。通过继承,可以避免重复编写相似的代码,并且可以实现代码的重用。
- 多态(Polymorphism):指可以使用一个父类类型的变量来引用不同子类类型的对象,从而实现对不同对象的统一操作。多态可以使得代码更加灵活,具有更好的可扩展性和可维护性。在 PHP 中,多态可以通过实现接口(interface)和使用抽象类(abstract class)来实现。
1.构造函数
构造函数(construct)是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,在创建对象的语句中与 new 运算符一起使用。
<?php
class Cat{
// 成员变量
public $name;
public $age;
// 构造函数
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
// 成员方法
public function details(){
echo '姓名:'.$this->name.'年龄:'.$this->age;
}
}
$animal = new Cat('小白',10);
$animal->details(); // 姓名:小白年龄:10
echo "<hr>";
注意:php不像java那样,可以提供多个构造器,只能提供一个构造器,若提供了有参构造函数,则必须在new时传入相应的初始化参数。
2.析构函数
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
<?php
class Plane{
public function __destruct()
{
echo '析构方法,对象结束生命周期时执行或者当前php脚本执行完毕时执行';
}
}
$p = new Plane();
echo '~~~~天气晴'.'<br>';
3.继承
PHP 使用关键字 extends 来继承一个类,PHP 不支持多继承,且使用final修饰的类无法再被继承。
<?php
final class Person{
public $name = '人类';
}
// 报错,提示final修饰的类无法被继承
class Student extends Person{
}
4.方法重写
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
<?php
class Person{
public $name = '人类';
public function showInfo(){
echo '我的名字是'.$this->name.'<br>';
}
}
class Student extends Person{
public $name = '学生';
public $cid = '小学一年级';
public function showInfo()
{
parent::showInfo();
echo '我的年级是:'.$this->cid;
}
}
$st1 = new Student();
$st1->showInfo();
// 我的名字是学生
// 我的年级是:小学一年级
$this
,指向当前实例对象的内容。
parent::showInfo()
或者 parent::xxxx()
,代表当前的子类调用从父类继承的方法,和Java中的super.()
类似.
5.访问控制
PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。
- public(公有):公有的类成员可以在任何地方被访问。
- protected(受保护):受保护的类成员则可以被其自身以及其子类和父类访问。
- private(私有):私有的类成员则只能被其定义所在的类访问。
6.接口
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
<?php
interface ComInterface{
public function connect();
public function transfer();
public function disconnect();
}
class MobilePhone implements ComInterface{
public function connect()
{
echo '连接开始'.'<br>';
}
public function transfer()
{
echo '连接传输'.'<br>';
}
public function disconnect()
{
echo '连接关闭'.'<br>';
}
}
$phone1 = new MobilePhone();
$phone1->connect();
$phone1->transfer();
$phone1->disconnect();
//连接开始
//连接传输
//连接关闭
<?php
interface behavior{
public function say();
public function jump();
}
interface behavior2{
public function eat();
}
class Superman implements behavior,behavior2 {
public function say()
{
echo '超人说:我在执行任务'.'<br>';
}
public function jump()
{
echo '超人,嗖的一下跳了出去!'.'<br>';
}
public function eat()
{
echo '超人:我不需要吃东西'.'<br>';
}
}
class Duck implements behavior,behavior2 {
public function say()
{
echo '鸭子:嘎嘎嘎'.'<br>';
}
public function jump()
{
echo '鸭子:左右摇摆的跳进了水里'.'<br>';
}
public function eat()
{
echo '鸭子吃食物'.'<br>';
}
}
$sp = new Superman();
$sp->say();
$sp->jump();
$sp->eat();
echo '<hr>';
$dk = new Duck();
$dk->say();
$dk->jump();
$dk->eat();
7.抽象类
任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象(abstract)的。
定义为抽象的类不能被实例化。
被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。
<?php
abstract class sport{
public abstract function status();
}
class Run extends sport{
public function status()
{
echo 'Run Run Run';
}
}
$runners = new Run();
$runners->status();// Run Run Run
8.静态static
声明类属性或方法为 static(静态),就可以不实例化类而直接访问。
静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
静态属性不可以由对象通过 -> 操作符来访问。
<?php
class Superman{
// 静态变量,通过类来访问
public static $name = '超人';
// 普通成员变量
public $address = '华盛顿';
// 静态方法,通过类来访问
public static function action(){
echo '镭射眼~~~~~~';
}
// 普通方法
public function showInfo(){
// 使用static 修饰的类变量或者方法时,需要通过 类名::xxx 的形式来访问
echo '姓名:'.Superman::$name.'<br>地址:'.$this->address;
}
}
// static 修饰的,无需实例化即可通过类名来调用
echo Superman::$name;
Superman::action();
echo '<hr>';
// 实例化对象,通过对象调用非static修饰的
$sp = new Superman();
$sp->showInfo();
9.final
final修饰的类,无法被继承,final修饰的方法无法被重写。
10. this ,self ,parent
this,self,parent三个关键字之间的区别,从字面上比较好理解,分别是指这、自己、父亲。
在类里面调用当前类的属性和方法有三种方法,分别是self、parent、$this
,这三个关键字的区别是self
用来指向当前的类;parent
用于指向当前类的父类,可以使用该关键字调用父类的属性和方法;$this
用来在类体内调用自身的属性和方法。
(1) this
$this
表示当前实例,在类的内部方法访问未声明为const及static的属性时,使用$this->value='phpernote';
的形式。
常见用法如:$this->属性
$this->方法
// 在get,set方法中,this频繁的使用,用来指定当前的实例的属性或者方法
class Man {
public $name ;
public $age;
public function __construct($name, $age)
{
$this->name = $name;
$this->age = $age;
}
public function getName()
{
return $this->name;
}
public function setName($name): void
{
$this->name = $name;
}
public function setAge($age): void
{
$this->age = $age;
}
public function getAge()
{
return $this->age;
}
}
(2) self
self用来指向当前的类
<?php
class Person{
function name(){
echo '类名'.get_class($this).'<br>';
}
}
class Man extends Person {
function name(){
echo '类名'.get_class($this).'<br>';
}
function nameSelf(){
self::name();
}
}
$m1 = new Man();
$m1->name();
$m1->nameSelf();
echo '<hr>';
$p = new Person();
$p->name();
(3) parent
parent用于指向当前类的父类,可以使用该关键字调用父类的属性和方法
<?php
class Person{
function say(){
echo 'hi'.'<br>';
}
}
class Man extends Person {
function saySomething(){
parent::say();
self::say();
}
function say()
{
echo 'hello'.'<br>';
}
}
$m1 = new Man();
$m1->saySomething();
// hi
// hello