Php 简明教程

Object Oriented Programming in PHP

我们可以想象我们的宇宙是由不同的物体组成的,如太阳、地球、月亮等。类似地,我们可以想象我们的汽车是由不同的物体组成的,如车轮、方向盘、齿轮等。同样,还存在面向对象编程概念,该概念将所有内容都假设为对象,并使用不同的对象实现软件。

We can imagine our universe made of different objects like sun, earth, moon etc. Similarly we can imagine our car made of different objects like wheel, steering, gear etc. Same way there is object oriented programming concepts which assume everything as an object and implement a software using different objects.

Object Oriented Concepts

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

Before we go in detail, lets define important terms related to Object Oriented Programming.

  1. Class − This is a programmer-defined data type, which includes local functions as well as local data. You can think of a class as a template for making many instances of the same kind (or class) of object.

  2. Object − An individual instance of the data structure defined by a class. You define a class once and then make many objects that belong to it. Objects are also known as instance.

  3. Member Variable − These are the variables defined inside a class. This data will be invisible to the outside of the class and can be accessed via member functions. These variables are called attribute of the object once an object is created.

  4. Member function − These are the function defined inside a class and are used to access object data.

  5. Inheritance − When a class is defined by inheriting existing function of a parent class then it is called inheritance. Here child class will inherit all or few member functions and variables of a parent class.

  6. Parent class − A class that is inherited from by another class. This is also called a base class or super class.

  7. Child Class − A class that inherits from another class. This is also called a subclass or derived class.

  8. Polymorphism − This is an object oriented concept where same function can be used for different purposes. For example function name will remain same but it take different number of arguments and can do different task.

  9. Overloading − a type of polymorphism in which some or all of operators have different implementations depending on the types of their arguments. Similarly functions can also be overloaded with different implementation.

  10. Data Abstraction − Any representation of data in which the implementation details are hidden (abstracted).

  11. Encapsulation − refers to a concept where we encapsulate all the data and member functions together to form an object.

  12. Constructor − refers to a special type of function which will be called automatically whenever there is an object formation from a class.

  13. Destructor − refers to a special type of function which will be called automatically whenever an object is deleted or goes out of scope.

Defining PHP Classes

在 PHP 中定义新类的通用格式如下 −

The general form for defining a new class in PHP is as follows −

<?php
   class phpClass {
      var $var1;
      var $var2 = "constant string";

      function myfunc ($arg1, $arg2) {
         [..]
      }
      [..]
   }
?>

下面是每一行的说明 −

Here is the description of each line −

  1. The special form class, followed by the name of the class that you want to define.

  2. A set of braces enclosing any number of variable declarations and function definitions.

  3. Variable declarations start with the special form var, which is followed by a conventional $ variable name; they may also have an initial assignment to a constant value.

  4. Function definitions look much like standalone PHP functions but are local to the class and will be used to set and access object data.

Example

下面是一个示例,定义了一个 Books 类型的类 −

Here is an example which defines a class of Books type −

<?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 是一个特殊变量,它引用同个对象,即它自身。

The variable $this is a special variable and it refers to the same object ie. itself.

Creating Objects in PHP

一旦定义了类,您就可以创建任意多的该类类型的对象。以下是如何使用 new 操作符创建对象的示例。

Once you defined your class, then you can create as many objects as you like of that class type. Following is an example of how to create object using new operator.

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

在这里,我们创建了三个对象,这些对象相互独立且单独存在。下一步,我们将看到如何访问成员函数和处理成员变量。

Here we have created three objects and these objects are independent of each other and they will have their existence separately. Next we will see how to access member function and process member variables.

Calling Member Functions

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

After creating your objects, you will be able to call member functions related to that object. One member function will be able to process member variable of related object only.

下面的示例演示了如何通过调用成员函数为这三本书设置标题和价格。

Following example shows how to set title and prices for the three books by calling member functions.

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

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

现在可以调用另一个成员函数来获取上述示例中设置的值 -

Now you call another member functions to get the values set by in above example −

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

这会产生以下结果 −

This will produce the following result −

Physics for High School
Advanced Chemistry
Algebra
10
15
7

Constructor Functions

构造函数是一种特殊类型的函数,它在创建对象时会自动调用。因此,通过构造函数初始化许多内容,我们可以充分利用此行为。

Constructor Functions are special type of functions which are called automatically whenever an object is created. So we take full advantage of this behaviour, by initializing many things through constructor functions.

PHP 提供了一个名为 __construct() 的特殊函数来定义一个构造函数。您可以将任意数量的参数传递到构造函数中。

PHP provides a special function called __construct() to define a constructor. You can pass as many as arguments you like into the constructor function.

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

Following example will create one constructor for Books class and it will initialize price and title for the book at the time of object creation.

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

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

Now we don’t need to call set function separately to set price and title. We can initialize these two member variables at the time of object creation only. Check following example below −

$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();

这会产生以下结果 −

This will produce the following result −

Physics for High School
Advanced Chemistry
Algebra
10
15
7

Destructor

像构造函数一样,您可以使用函数 __destruct() 定义一个析构函数。您可以在析构函数中释放所有资源。

Like a constructor function you can define a destructor function using function __destruct(). You can release all the resources with-in a destructor.

Inheritance

PHP 类定义可以使用 extends 子句从父类定义中继承,语法如下:

PHP class definitions can optionally inherit from a parent class definition by using the extends clause. The syntax is as follows −

class Child extends Parent {
   <definition body>
}

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

The effect of inheritance is that the child class (or subclass or derived class) has the following characteristics −

  1. Automatically has all the member variable declarations of the parent class.

  2. Automatically has all the same member functions as the parent, which (by default) will work the same way as those functions do in the parent.

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

Following example inherit Books class and adds more functionality based on the requirement.

class Novel extends Books {
   var $publisher;

   function setPublisher($par){
      $this->publisher = $par;
   }

   function getPublisher(){
      echo $this->publisher. "<br />";
   }
}

现在,除了继承的函数之外,Novel 类还保留了两个其他成员函数。

Now apart from inherited functions, class Novel keeps two additional member functions.

Function Overriding

子类中的函数定义覆盖了父类中同名定义。在子类中,我们可以修改从父类继承的函数的定义。

Function definitions in child classes override definitions with the same name in parent classes. In a child class, we can modify the definition of a function inherited from parent class.

在以下示例中,getPrice 和 getTitle 函数被覆盖以返回一些值。

In the following example getPrice and getTitle functions are overridden to return some values.

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

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

Public Members

除非您另行指明,否则类的属性和方法均为公共的。也就是说,它们可以在三种可能的情况下进行访问 -

Unless you specify otherwise, properties and methods of a class are public. That is to say, they may be accessed in three possible situations −

  1. From outside the class in which it is declared

  2. From within the class in which it is declared

  3. From within another class that implements the class in which it is declared

到目前为止,我们已经看到了所有成员作为公共成员。如果您希望限制类成员的可访问性,则可以将类成员定义为 privateprotected

Till now we have seen all members as public members. If you wish to limit the accessibility of the members of a class then you define class members as private or protected.

Private members

通过将成员设为私有,你可以限制其对声明它的类的可访问性。私有成员无法从继承声明它的类的类中引用,也无法从类外部访问。

By designating a member private, you limit its accessibility to the class in which it is declared. The private member cannot be referred to from classes that inherit the class in which it is declared and cannot be accessed from outside the class.

可以使用成员前面的 private 关键字将类成员设为私有。

A class member can be made private by using private keyword infront of the member.

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,因为它们声明为私有。

When MyClass class is inherited by another class using extends, myPublicFunction() will be visible, as will $driver. The extending class will not have any awareness of or access to myPrivateFunction and $car, because they are declared private.

Protected members

受保护的属性或方法在其声明所在的类以及该类的扩展类中都可以访问。受保护的成员在除了这两种类之外的类中不可用。可以使用成员前面的 protected 关键字将类成员设为受保护。

A protected property or method is accessible in the class in which it is declared, as well as in classes that extend that class. Protected members are not available outside of those two kinds of classes. A class member can be made protected by using protected keyword in front of the member.

以下是 MyClass 的不同版本 −

Here is different version of 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!");
   }
}

Interfaces

接口的定义是为了向实现者提供通用的函数名称。不同的实现者可以根据其要求来实现这些接口。你可以说,接口是开发人员实现的骨架。

Interfaces are defined to provide a common function names to the implementers. Different implementors can implement those interfaces according to their requirements. You can say, interfaces are skeletons which are implemented by developers.

从 PHP5 起,可以像这样定义接口 −

As of PHP5, it is possible to define an interface, like this −

interface Mail {
   public function sendMail();
}

然后,如果另一个类实现了该接口,如下所示 −

Then, if another class implemented that interface, like this −

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

Constants

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

A constant is somewhat like a variable, in that it holds a value, but is really more like a function because a constant is immutable. Once you declare a constant, it does not change.

声明常量很简单,在 MyClass 的此版本中就是如此 −

Declaring one constant is easy, as is done in this version of 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 以外的任何值。请注意,与变量名称不同,常量的名称没有前导 $。

In this class, requiredMargin is a constant. It is declared with the keyword const, and under no circumstances can it be changed to anything other than 1.7. Note that the constant’s name does not have a leading $, as variable names do.

Abstract Classes

抽象类是不可实例化的,只能继承。使用关键字 abstract 声明抽象类,如下所示 −

An abstract class is one that cannot be instantiated, only inherited. You declare an abstract class with the keyword abstract, like this −

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

When inheriting from an abstract class, all methods marked abstract in the parent’s class declaration must be defined by the child; additionally, these methods must be defined with the same visibility.

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

请注意,抽象类中的函数定义也必须以前导关键字 abstract 为前缀。在非抽象类中不能有抽象函数定义。

Note that function definitions inside an abstract class must also be preceded by the keyword abstract. It is not legal to have abstract function definitions inside a non-abstract class.

Static Keyword

将类成员或方法声明为 static 使它们可以在不需要实例化类的情况下对其进行访问。声明为 static 的成员无法通过实例化的类对象进行访问(虽然静态方法可以访问)。

Declaring class members or methods as static makes them accessible without needing an instantiation of the class. A member declared as static can not be accessed with an instantiated class object (though a static method can).

尝试使用以下示例 −

Try out following example −

<?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";
?>

Final Keyword

PHP 5 引入了 final 关键字,它通过使用 final 作为定义前缀来阻止子类覆盖方法。如果类本身被定义为 final,则无法使用其扩展。

PHP 5 introduces the final keyword, which prevents child classes from overriding a method by prefixing the definition with final. If the class itself is being defined final then it cannot be extended.

以下示例导致致命错误:无法覆盖 final 方法 BaseClass::moreTesting()

Following example results in Fatal error: Cannot override final method 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>";
      }
   }
?>

Calling parent constructors

让我们通过显式地调用父类的构造函数,然后再执行实例化子类时除了需要的所有其他操作之外的任何操作来编写它,而不是为子类编写一个全新的构造函数。这里有一个简单的示例 −

Instead of writing an entirely new constructor for the subclass, let’s write it by calling the parent’s constructor explicitly and then doing whatever is necessary in addition for instantiation of the subclass. Here’s a simple example −

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);
   }
}
In this example, we have a parent class (Name), which has a two-argument constructor, and a subclass (NameSub1), which has a three-argument constructor. The constructor of NameSub1 functions by calling its parent constructor explicitly using the

syntax (passing two of its arguments along) and then setting an additional field. Similarly, NameSub1 defines its non constructor toString() function in terms of the parent function that it overrides.

NOTE − 构造函数可以使用与类名称相同的名称来定义。它在上面的示例中被定义。

NOTE − A constructor can be defined with the same name as the name of a class. It is defined in above example.