PHP中面向对象的编程

我们可以想象我们的宇宙由不同的物体组成,如太阳,地球,月亮等.同样,我们可以想象我们的汽车由不同的物体组成,如轮子,转向,齿轮等.同样的方式是面向对象的编程概念,假设一切都像一个对象并使用不同的对象实现一个软件.

面向对象的概念

在我们详细介绍之前,让我们定义与面向对象编程相关的重要术语.

  • Class : 这是程序员定义的数据类型,包括本地函数和本地数据.您可以将类视为用于创建对象类型(或类)的许多实例的模板.

  • 对象 &减去;由类定义的数据结构的单个实例.您可以定义一次类,然后创建属于它的许多对象.对象也称为实例.

  • 成员变量 : 这些是在类中定义的变量.该数据对于类的外部是不可见的,并且可以通过成员函数访问.创建对象后,这些变量称为对象的属性.

  • 成员函数 : 这些是在类中定义的函数,用于访问对象数据.

  • 继承 : 当通过继承父类的现有函数来定义类时,它被称为继承.这里子类将继承父类的所有或几个成员函数和变量.

  • 父类 : 从另一个类继承的类.这也称为基类或超类.

  • 子类 : 从另一个类继承的类.这也称为子类或派生类.

  • 多态性 : 这是一个面向对象的概念,其中相同的功能可用于不同的目的.例如,函数名称将保持不变,但它可以使用不同数量的参数,并且可以执行不同的任务.

  • 重载 : 一种多态,其中一些或所有运算符根据其参数的类型具有不同的实现.类似地,函数也可以通过不同的实现重载.

  • 数据抽象 : 隐藏(抽象)实现细节的任何数据表示.

  • 封装 : 是指我们将所有数据和成员函数封装在一起形成对象的概念.

  • 构造函数 : 是指一种特殊类型的函数,只要从类中形成对象,就会自动调用它.

  • 析构函数 : 指的是一种特殊类型的函数,只要删除一个对象或超出范围就会自动调用它.

定义PHP类

在PHP中定义新类的一般形式如下 :

<?php
   class phpClass {
      var $var1;
      var $var2 = "constant string";
      
      function myfunc ($arg1, $arg2) {
         [..]
      }
      [..]
   }
?>

以下是每行的说明 :

  • 特殊形式,后跟您要定义的类的名称.

  • 一组括号包含任意数量的变量声明和函数定义.

  • 变量声明以特殊形式 var 开头,后面是常规$ variable name;它们也可能具有常量值的初始赋值.

  • 函数定义看起来很像独立的PHP函数,但它们是类的本地函数,并将用于设置和访问对象数据.

示例

这是一个定义一类书籍的例子类型和减号;

<?php
   class Books {
      /* Member variables */
      var $price;
      var $title;
      
      /* Member functions */
      function setPrice($par){
         $this->price = $par;
      }
      
      function getPrice(){
         echo $this->price ."<br/>";
      }
      
      function setTitle($par){
         $this->title = $par;
      }
      
      function getTitle(){
         echo $this->title ." <br/>";
      }
   }
?>

变量 $ this 是一个特殊变量,它引用同一个对象即.它本身.

用PHP创建对象

一旦定义了类,就可以创建任意数量的类对象.以下是如何使用 new 运算符创建对象的示例.

$physics = new Books;
$maths = new Books;
$chemistry = new Books;

这里我们创建了三个对象,这些对象彼此独立,它们将分别存在.接下来我们将看到如何访问成员函数和进程成员变量.

调用成员函数

创建对象后,您将能够调用与该对象相关的成员函数.一个成员函数只能处理相关对象的成员变量.

以下示例显示如何通过调用成员函数来设置三本书的标题和价格.

$physics->setTitle( "Physics for High School" );
$chemistry->setTitle( "Advanced Chemistry" );
$maths->setTitle( "Algebra" );

$physics->setPrice( 10 );
$chemistry->setPrice( 15 );
$maths->setPrice( 7 );

现在你调用另一个成员函数来获取上面示例中设置的值 :

$physics->getTitle();
$chemistry->getTitle();
$maths->getTitle();
$physics->getPrice();
$chemistry->getPrice();
$maths->getPrice();

这将产生以下结果 :

Physics for High School
Advanced Chemistry
Algebra
10
15
7

构造函数

构造函数是特殊类型的函数,只要创建对象,就会自动调用这些函数.所以我们通过构造函数初始化很多东西来充分利用这种行为.

PHP提供了一个名为 __ construct()的特殊函数来定义构造函数.您可以将任意数量的参数传递给构造函数.

以下示例将为Books类创建一个构造函数,它将在创建对象时初始化该书的价格和标题.

function __construct( $par1, $par2 ) {
   $this->title = $par1;
   $this->price = $par2;
}

现在我们不需要单独调用set函数来设置价格和标题.我们只能在创建对象时初始化这两个成员变量.检查以下示例 :

$physics = new Books( "Physics for High School", 10 );
$maths = new Books ( "Advanced Chemistry", 15 );
$chemistry = new Books ("Algebra", 7 );

/* Get those set values */
$physics->getTitle();
$chemistry->getTitle();
$maths->getTitle();

$physics->getPrice();
$chemistry->getPrice();
$maths->getPrice();

这将产生以下结果 :

  Physics for High School
  Advanced Chemistry
  Algebra
  10
  15
  7

析构函数

与构造函数一样,您可以使用函数 __ destruct()定义析构函数.您可以使用析构函数释放所有资源.

继承

PHP类定义可以选择通过使用extends从父类定义继承条款.语法如下 :

class Child extends Parent {
   <definition body>
}

继承的效果是子类(或子类或派生类)具有以下特征 :

  • 自动拥有父类的所有成员变量声明.

  • 自动拥有与父项相同的所有成员函数,这些函数(默认情况下)的工作方式与父项中的函数相同.

以下示例继承Books类并根据需求添加更多功能.

class Novel extends Books {
   var $publisher;
   
   function setPublisher($par){
      $this->publisher = $par;
   }
   
   function getPublisher(){
      echo $this->publisher. "<br />";
   }
}

现在除了继承的函数之外,Novel还保留了两个额外的成员函数.

函数重写

子类中的函数定义会覆盖父类中具有相同名称的定义.在子类中,我们可以修改从父类继承的函数的定义.

在下面的示例中,将重写getPrice和getTitle函数以返回一些值.

function getPrice() {
   echo $this->price . "<br/>";
   return $this->price;
}
   
function getTitle(){
   echo $this->title . "<br/>";
   return $this->title;
}

公共成员

除非另有说明,否则类的属性和方法是公共的.也就是说,可以在三种可能的情况下访问它们 :

  • 从声明它的类之外

  • 在声明它的类中

  • 从另一个类中实现声明它的类

直到现在我们已经看到所有成员都是公共成员.如果您希望限制班级成员的可访问性,则将班级成员定义为私人受保护.

私人成员

通过将成员私有指定,您可以将其可访问性限制为声明它的类.私有成员不能从继承声明它的类的类引用,也不能从类外部访问.

可以使用将类成员设为私有私人关键字infront成员.

class MyClass {
   private $car = "skoda";
   $driver = "SRK";
   
   function __construct($par) {
      // Statements here run every time
      // an instance of the class
      // is created.
   }
   
   function myPublicFunction() {
      return("I'm visible!");
   }
   
   private function myPrivateFunction() {
      return("I'm  not visible outside!");
   }
}

MyClass 类由另一个使用extends继承的类时,myPublicFunction()将可见,$ driver也是如此.扩展类不会对myPrivateFunction和$ car有任何意识或访问权限,因为它们被声明为私有.

受保护的成员

受保护的属性或者方法可以在声明它的类中以及扩展该类的类中访问.受保护的成员在这两类之外是不可用的.可以通过在成员面前使用 protected 关键字来保护类成员.

以下是MyClass的不同版本 :

class MyClass {
   protected $car = "skoda";
   $driver = "SRK";

   function __construct($par) {
      // Statements here run every time
      // an instance of the class
      // is created.
   }
   
   function myPublicFunction() {
      return("I'm visible!");
   }
   
   protected function myPrivateFunction() {
      return("I'm  visible in child class!");
   }
}

接口

定义接口以提供常用的函数名称实施者.不同的实现者可以根据需要实现这些接口.你可以说,接口是由开发人员实现的骨架.

从PHP5开始,可以定义一个接口,比如这个 :

interface Mail {
   public function sendMail();
}

然后,如果另一个类实现了该接口,就像这个 :

class Report implements Mail {
   // sendMail() Definition goes here
}

常数

常量有点像变量,因为它保存一个值,但实际上更像是一个函数,因为常量是不可变的.一旦你声明一个常量,它就不会改变.

声明一个常量很容易,就像在这个版本的MyClass中做的那样&减去;

class MyClass {
   const requiredMargin = 1.7;
   
   function __construct($incomingValue) {
      // Statements here run every time
      // an instance of the class
      // is created.
   }
}

在这个类中,requiredMargin是一个常量.它使用关键字const声明,并且在任何情况下都不能将其更改为1.7以外的任何值.请注意,常量的名称没有前导$,因为变量名称可以.

抽象类

抽象类是无法实例化的类,只是继承.您使用关键字 abstract 声明一个抽象类,如此 :

从抽象类继承时,父类声明中标记为abstract的所有方法必须是由孩子定义;此外,必须使用相同的可见性定义这些方法.

abstract class MyAbstractClass {
   abstract function myAbstractFunction() {
   }
}

请注意,抽象类中的函数定义也必须以关键字abstract开头.在非抽象类中包含抽象函数定义是不合法的.

静态关键字

将类成员或方法声明为静态使它们可访问无需实例化类.声明为static的成员无法使用实例化的类对象访问(虽然静态方法可以).

尝试以下示例 :

<?php
   class Foo {
      public static $my_static = 'foo';
      
      public function staticValue() {
         return self::$my_static;
      }
   }
	
   print Foo::$my_static . "\n";
   $foo = new Foo();
   
   print $foo->staticValue() . "\n";
?>

最终关键字

PHP 5引入了final关键字,它阻止子类通过为定义添加前缀来覆盖方法决赛.如果类本身被定义为final,则无法扩展.

以下示例结果出现致命错误:无法覆盖最终方法BaseClass :: moreTesting()

<?php

   class BaseClass {
      public function test() {
         echo "BaseClass::test() called<br>";
      }
      
      final public function moreTesting() {
         echo "BaseClass::moreTesting() called<br>";
      }
   }
   
   class ChildClass extends BaseClass {
      public function moreTesting() {
         echo "ChildClass::moreTesting() called<br>";
      }
   }
?>

调用父构造函数

不要为子类编写全新的构造函数,而是通过调用父类来编写它显式构造函数,然后执行除了实例化子类之外所需的任何操作.这是一个简单的例子 :

class Name {
   var $_firstName;
   var $_lastName;
   
   function Name($first_name, $last_name) {
      $this->_firstName = $first_name;
      $this->_lastName = $last_name;
   }
   
   function toString() {
      return($this->_lastName .", " .$this->_firstName);
   }
}
class NameSub1 extends Name {
   var $_middleInitial;
   
   function NameSub1($first_name, $middle_initial, $last_name) {
      Name::Name($first_name, $last_name);
      $this->_middleInitial = $middle_initial;
   }
   
   function toString() {
      return(Name::toString() . " " . $this->_middleInitial);
   }
}

在这个例子中,我们有一个父类(Name),它有一个双参数构造函数,子类(NameSub1),它有一个三参数构造函数. NameSub1的构造函数通过使用::语法显式调用其父构造函数(传递其两个参数)然后设置一个附加字段来起作用.类似地,NameSub1根据它覆盖的父函数定义其非构造函数toString()函数.

注意 : 可以使用与类名相同的名称定义构造函数.它在上面的例子中定义.