跳转到内容

PHP 编程/类

来自维基教科书,开放的书籍,开放的世界

类是由三种称为成员的项组成的结构,即

  1. 常量;
  2. 称为“属性”的变量;
  3. 称为“方法”的函数。

它们中的每一个都以可见性声明,可见性可以是显式的(从“私有”、“保护”和“公共”),也可以是隐式的(即省略声明,仅允许用于默认值为“公共”的方法)。

对象是类的实例,在其中可以调用其类的所有方法(如果有),并可以为其类的成员(如果有)提供新的值,覆盖默认值。

一个简单的类可以定义如下

  <?php
  
  /* Start the class */
  class Html {
  
     /*
       Declare a public member named "br" with a default value of "&lt;br /&gt;" (the
       XHTML line break)
     */
     public $br = '&lt;br /&gt;';
  
  
     /*
       Declare a public (by default) method named "printLn" requiring an argument
       named "message"
     */
     function printLn ($message) {
        
        /*
          Echo the "message" argument followed by the value of the "br" member (accessed
          through the use of the "$this" keyword (that represents the current object),
          the "->" operator (used to access members) and the member's name ''without''
          the "$" character.
        */
        echo $message . $this->br;
  
     }
  }
  ?>

但是,仅仅因为你创建了一个类并不意味着你可以使用其中的任何东西。类是一个抽象的实体。它是一种表示“以下是如何创建”的方法Html-类型的对象,以及它们的作用。” 为了使用类的成员,你必须创建一个该类的实例

也就是说,你必须实际创建一个“Html”对象并使用它。

定义完类之后,你将要尝试它。对象是类的实例。在 PHP 中使用对象如下

<?php
$myPage = new Html; // Creates an instance of the Html class
$myPage->printLn('This is some text'); // Prints "This is some text&lt;br /&gt;"
?>

这段代码中的新概念是

  • new 关键字 — 用于创建一个新的对象实例,在本例中是类 Html 的一个对象。
  • -> 运算符 — 用于访问实例化对象的成员或方法,在本例中是方法 printLn()

现在,换行符的表示形式是在类的成员中定义的,这使你能够更改它。请注意,更改仅会影响一个实例,而不是整个类。以下是一个示例(请注意,“<br>” 是一个 HTML 换行符,“<br />” 是一个 XHTML 换行符)

<?php
$myPage = new Html; // Creates an instance of the Html class
$myOldHtmlPage = new Html; // Creates another instance of the Html class
$myOldHtmlPage->br = "&lt;br&gt;"; // Changes the value of the "br" member of the "$myOldHtmlPage" instance to the old HTML value
$myOldHtmlPage->printLn('This is some text'); // Prints "This is some text&lt;br&gt;", the new value of the member is used
$myPage->printLn('This is some text'); // Prints "This is some text&lt;br /&gt;", the default value of the member is kept
?>

但是,请注意,最好避免修改实例的成员:为了允许实例进行可能的约束验证,应该改为在类中添加(并在处理实例时使用)“get_br” 和 “set_br” 方法来获取和设置成员的值,同时允许实例执行测试,并可能拒绝更改。

作用域

[编辑 | 编辑源代码]

类中项的作用域定义了谁可以调用它(对于方法)或读取/更改它的值(对于属性)。

作用域定义对于属性是强制性的,对于方法是可选的,其中“公共”是未指定任何内容时的默认值。

公共项可以在任何地方访问。

在类中定义的保护项可以被实例化此类或此类的子类的对象访问。

在类中定义的私有项可以被实例化该类的对象访问。

它们使用 const 声明(而不是在过程编程中使用 define()),可以选择性地后面跟着一个默认值

const MY_CONSTANT_1 = 0;

它们可以通过反射检索

$myClass1::getConstants();

尽管将类属性声明为公共会使它们更容易使用,但一般不建议这样做。如果你决定在类的未来版本中对公共属性执行任何类型的检查,或者将其存储在另一个附加属性中以用于缓存目的,你将无法做到这一点,因为其余代码仍将使用公共属性而没有任何检查。

因此,人们应该更喜欢(除了特殊情况)不允许对属性进行公共访问,并提供简单的“get_foo”和“set_foo”方法来返回或覆盖它们,从而在需要时保留添加复杂性的可能性。

它们可以通过反射检索

$myClass1::getProperties();

由于方法提供了对象与外部世界的实际接口,因此大多数方法都应该公开访问。

更准确地说,任何旨在从外部调用的方法都应该是公共的。但是,仅用于内部使用且不是接口一部分的方法不应该是公共的。一个典型的例子是一个对象抽象与数据库的连接,同时提供一个缓存系统。应该存在不同的公共方法来允许与外部世界的交互,但是,例如,将原始 SQL 请求发送到数据库的方法不应该是公共的,因为任何调用它的外部代码都会绕过缓存,并可能导致无用的负载或(更糟)数据丢失,因为数据库的数据可能已过期(如果缓存中发生了延迟更改)。

它们可以通过反射检索

$myClass1::getMethods();

实际应用

[编辑 | 编辑源代码]

上面的示例没有说明类和对象的情况。为什么为了访问函数而去创建所有这些额外的结构呢?

让我们举一个可以显示这种方法如何有用的例子

<?php
class Html {
   private $source = "";
   public function printLn ($message) {
      echo $this->source .= $message . "&lt;br /&gt;";
   }
   public function show () {
      echo $this->source;
   }
}

$elvis = new Html();
$goth = new Html();

$elvis->printLn("Welcome to my Elvis Fan Page! Uh-huh, uh-huh, uh-huh.");
$goth->printLn("Entree the Goth Poetry Labyrinth of Spoooky Doooommmm...");
$elvis->show(); 
?>

一些需要注意的地方

  • 语句echo $this->source .= $message ."&lt;br /&gt;";首先更改私有属性的值$source然后打印更改后的值。更改后的值已保存。
  • 不同的副本$source属性存在于每个实例中Html类。
  • printLnshow函数引用的是同一个副本$source它被调用用于他们的对象。 (当我调用$elvisprintLn函数时,它会改变$elvis$source变量和语句$elvis->show();打印改变后的值$source).
  • 使用标准变量和方法,将会有更大的风险将错误的内容发送到错误的页面。这对于我的网站访客来说可能是极其混乱的。

现在我们开始看到如何使用类和对象来节省时间和麻烦。我们现在可以轻松地同时管理两个潜在的网页,将正确的内容打印到每个页面。完成后,我们只需调用一个页面的show函数将该页面的 html 源代码发送到输出流。

我可以通过向管理类添加变量和函数,为所有对象添加更多功能,并且可以根据需要添加更多对象,只需声明它们即可。事实上,我的程序越复杂,使用面向对象编程来管理一切就越容易。


华夏公益教科书