文章目录
- 1.数组
- 1.1创建数组
- 1.2遍历数值数组
- 1.3关联数组(自定义键名-id)
- 1.4遍历关联数组
- 2.数组排序
- 2.1对数组进行升降序排列
- 2.2根据关联数组的值进行升降序
- 2.3根据关联数组的键进行升降序
- 3.超级全局变量
- 3.1$GLOBALS
- 3.2$_SERVER
- 3.3 $_REQUEST
- 3.4 _ P O S T 和 \_POST和 _POST和\_GET
- 4.循环
- 4.1 while循环
- 4.2 do...while循环
- 4.3 for循环
- 4.4 foreach 循环
- 5.函数
- 5.1无参
- 5.2有参
- 5.3有返回值
- 6.魔术常量
- 7.命名空间
- 7.1定义命名空间
- 7.2子命名空间
- 7.3命名空间的使用
- 7.4命名空间和动态语言特征
- 7.5namespace关键字和__NAMESPACE__常量
- 7.6使用命名空间:别名/导入
- 7.7使用命名空间:后备全局函数/常量
- 7.8全局空间
- 7.9命名空间的顺序
- 8.面向对象
- 8.1类定义
- 8.2创建对象
- 8.3构造函数
- 8.4析构函数
- 8.5继承
- 8.6方法重写
- 8.7访问控制
- 8.7.1属性的访问控制
- 8.7.2方法的访问控制
- 8.8接口(API?)
- 8.9常量
- 8.10抽象类
- 8.11Static 关键字
- 8.12Final 关键字
- 8.13调用父类构造方法
1.数组
在 PHP 中,array() 函数用于创建数组:
在 PHP 中,有三种类型的数组:
- 数值数组 - 带有数字 ID 键的数组
- 关联数组 - 带有指定的键的数组,每个键关联一个值
- 多维数组 - 包含一个或多个数组的数组
1.1创建数组
count() 函数用于返回数组的长度(元素的数量):
<?php
$cars=array("Volvo","BMW","Toyota");
echo "I like " . $cars[0] . ", " . $cars[1] . " and " . $cars[2] . ".";
echo count($cars);
?>
1.2遍历数值数组
<?php
$cars=array("Volvo","BMW","Toyota");
$arrlength=count($cars);
for($x=0;$x<$arrlength;$x++)
{
echo $cars[$x];
echo "<br>";
}
?>
1.3关联数组(自定义键名-id)
<?php
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
echo "Peter is " . $age['Peter'] . " years old.";
?>
1.4遍历关联数组
<?php
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
foreach($age as $x=>$x_value)
{
echo "Key=" . $x . ", Value=" . $x_value;
echo "<br>";
}
?>
2.数组排序
- sort() - 对数组进行升序排列
- rsort() - 对数组进行降序排列
- asort() - 根据关联数组的值,对数组进行升序排列
- ksort() - 根据关联数组的键,对数组进行升序排列
- arsort() - 根据关联数组的值,对数组进行降序排列
- krsort() - 根据关联数组的键,对数组进行降序排列
2.1对数组进行升降序排列
PS:print_r() 函数用于打印变量,以更容易理解的形式展示。如果给出的是 string、integer 或 float 类型变量,将打印变量值本身。如果给出的是 array,将会按照一定格式显示键和元素。object 与数组类似。
<?php
$cars=array("Volvo","BMW","Toyota");
sort($cars);
print_r($cars);
echo "<br>";
rsort($cars);
print_r($cars);
?>
2.2根据关联数组的值进行升降序
<?php
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
asort($age);
print_r($age);
echo "<br>";
arsort($age);
print_r($age);
?>
2.3根据关联数组的键进行升降序
<?php
$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43");
ksort($age);
print_r($age);
echo "<br>";
krsort($age);
print_r($age);
?>
3.超级全局变量
PS:PHP中预定义了几个超级全局变量(superglobals) ,这意味着它们在一个脚本的全部作用域中都可用。 你不需要特别说明,就可以在函数及类中使用。
PHP 超级全局变量列表:
- $GLOBALS
- $_SERVER
- $_REQUEST
- $_POST
- $_GET
- $_FILES
- $_ENV
- $_COOKIE
- $_SESSION
3.1$GLOBALS
$GLOBALS 是一个包含了全部变量的全局组合数组。变量的名字就是数组的键。
<?php
$x = 75;
$y = 25;
function addition()
{
$GLOBALS['z'] = $GLOBALS['x'] + $GLOBALS['y'];
}
addition();
echo $z;
?>
3.2$_SERVER
$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。不能保证每个服务器都提供全部项目;服务器可能会忽略一些,或者提供一些没有在这里列举出来的项目。
元素/代码 | 描述 |
---|---|
$_SERVER[‘PHP_SELF’] | 当前执行脚本的文件名,与 document root 有关。例如,在地址为 http://example/test.php/foo.bar 的脚本中使用 $_SERVER[‘PHP_SELF’] 将得到 /test.php/foo.bar。FILE 常量包含当前(例如包含)文件的完整路径和文件名。 从 PHP 4.3.0 版本开始,如果 PHP 以命令行模式运行,这个变量将包含脚本名。之前的版本该变量不可用。 |
$_SERVER[‘GATEWAY_INTERFACE’] | 服务器使用的 CGI 规范的版本;例如,“CGI/1.1”。 |
$_SERVER[‘SERVER_ADDR’] | 当前运行脚本所在的服务器的 IP 地址。 |
$_SERVER[‘SERVER_NAME’] | 当前运行脚本所在的服务器的主机名。如果脚本运行于虚拟主机中,该名称是由那个虚拟主机所设置的值决定。(如: www.runoob) |
$_SERVER[‘SERVER_SOFTWARE’] | 服务器标识字符串,在响应请求时的头信息中给出。 (如:Apache/2.2.24) |
$_SERVER[‘SERVER_PROTOCOL’] | 请求页面时通信协议的名称和版本。例如,“HTTP/1.0”。 |
$_SERVER[‘REQUEST_METHOD’] | 访问页面使用的请求方法;例如,“GET”, “HEAD”,“POST”,“PUT”。 |
$_SERVER[‘REQUEST_TIME’] | 请求开始时的时间戳。从 PHP 5.1.0 起可用。 (如:1377687496) |
$_SERVER[‘QUERY_STRING’] | query string(查询字符串),如果有的话,通过它进行页面访问。 |
$_SERVER[‘HTTP_ACCEPT’] | 当前请求头中 Accept: 项的内容,如果存在的话。 |
$_SERVER[‘HTTP_ACCEPT_CHARSET’] | 当前请求头中 Accept-Charset: 项的内容,如果存在的话。例如:“iso-8859-1,*,utf-8”。 |
$_SERVER[‘HTTP_HOST’] | 当前请求头中 Host: 项的内容,如果存在的话。 |
$_SERVER[‘HTTP_REFERER’] | 引导用户代理到当前页的前一页的地址(如果存在)。由 user agent 设置决定。并不是所有的用户代理都会设置该项,有的还提供了修改 HTTP_REFERER 的功能。简言之,该值并不可信。) |
$_SERVER[‘HTTPS’] | 如果脚本是通过 HTTPS 协议被访问,则被设为一个非空的值。 |
$_SERVER[‘REMOTE_ADDR’] | 浏览当前页面的用户的 IP 地址。 |
$_SERVER[‘REMOTE_HOST’] | 浏览当前页面的用户的主机名。DNS 反向解析不依赖于用户的 REMOTE_ADDR。 |
$_SERVER[‘REMOTE_PORT’] | 用户机器上连接到 Web 服务器所使用的端口号。 |
$_SERVER[‘SCRIPT_FILENAME’] | 当前执行脚本的绝对路径。 |
$_SERVER[‘SERVER_ADMIN’] | 该值指明了 Apache 服务器配置文件中的 SERVER_ADMIN 参数。如果脚本运行在一个虚拟主机上,则该值是那个虚拟主机的值。(如:someone@runoob) |
$_SERVER[‘SERVER_PORT’] | Web 服务器使用的端口。默认值为 “80”。如果使用 SSL 安全连接,则这个值为用户设置的 HTTP 端口。 |
$_SERVER[‘SERVER_SIGNATURE’] | 包含了服务器版本和虚拟主机名的字符串。 |
$_SERVER[‘PATH_TRANSLATED’] | 当前脚本所在文件系统(非文档根目录)的基本路径。这是在服务器进行虚拟到真实路径的映像后的结果。 |
$_SERVER[‘SCRIPT_NAME’] | 包含当前脚本的路径。这在页面需要指向自己时非常有用。FILE 常量包含当前脚本(例如包含文件)的完整路径和文件名。 |
$_SERVER[‘SCRIPT_URI’] | URI 用来指定要访问的页面。例如 “/index.html”。 |
<?php
echo $_SERVER['PHP_SELF'];
echo "<br>";
echo $_SERVER['SERVER_NAME'];
echo "<br>";
echo $_SERVER['HTTP_HOST'];
echo "<br>";
echo $_SERVER['HTTP_REFERER'];//没有上一个页面,所以为空
echo "<br>";
echo $_SERVER['HTTP_USER_AGENT'];
echo "<br>";
echo $_SERVER['SCRIPT_NAME'];
?>
3.3 $_REQUEST
$_REQUEST 用于收集HTML表单提交的数据。(好像用的挺少的)
<html>
<body>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
Name: <input type="text" name="fname">
<input type="submit">
</form>
<?php
$name = $_REQUEST['fname'];
echo $name;
?>
</body>
</html>
3.4 _ P O S T 和 \_POST和 _POST和_GET
都是用于收集表单数据
POST的数据对任何人都不可见,URL地址栏看不到
GET的数据对任何人都可见,URL地址栏可以看到
<html>
<body>
<form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">
Name: <input type="text" name="fname">
<input type="submit">
</form>
<?php
$name = $_POST['fname'];
echo 'POST提交'.$name;
?>
<br/>
<a href="test.php?subject=PHP&web=runoob">Test $GET</a><br/>
<?php
echo 'GET提交'.$_GET[subject].' '.$_GET[web].'';
?>
</body>
</html>
4.循环
在 PHP 中,提供了下列循环语句:
- while - 只要指定的条件成立,则循环执行代码块
- do…while - 首先执行一次代码块,然后在指定的条件成立时重复这个循环
- for - 循环执行代码块指定的次数
- foreach - 根据数组中每个元素来循环代码块
4.1 while循环
先判断再执行
<?php
$i=1;
while($i<=5)
{
echo "The number is " . $i . "<br>";
$i++;
}
?>
4.2 do…while循环
先执行一次,再做判断
<?php
$i=1;
do
{
$i++;
echo "The number is " . $i . "<br>";
}
while ($i<=5);
?>
4.3 for循环
<?php
for ($i=1; $i<=5; $i++)
{
echo "The number is " . $i . "<br>";
}
?>
4.4 foreach 循环
foreach 循环用于遍历数组。(遍历数据库中的表经常用)
<?php
$x=array("one","two","three");
foreach ($x as $value)
{
echo $value . "<br>";
}
?>
5.函数
PHP 函数准则:
- 函数的名称应该提示出它的功能
- 函数名称以字母或下划线开头(不能以数字开头)
5.1无参
<?php
function writeName()
{
echo "Kai Jim Refsnes";
}
echo "My name is ";
writeName();
?>
5.2有参
<?php
function writeName($fname)
{
echo $fname . " Refsnes.<br>";
}
echo "My name is ";
writeName("Kai Jim");
echo "My sister's name is ";
writeName("Hege");
echo "My brother's name is ";
writeName("Stale");
?>
5.3有返回值
<?php
function add($x,$y)
{
$total=$x+$y;
return $total;
}
echo "1 + 16 = " . add(1,16);
?>
6.魔术常量
魔术常量的值随着它们在代码中的位置改变而改变 。(有八个)
- _LINE_ 文件中的当前行号。
- _FILE_ 文件的完整路径和文件名。
- _DIR_ 文件所在的目录。
- _FUNCTION_ 函数名称
- _CLASS_ 类的名称
- _TRAIT_ Trait 名包括其被声明的作用区域
- _METHOD_ 类的方法名(类::函数)
- __NAMESPASE __ 当前命名空间的名称
<?php
namespace MyProject;
echo '这是第 " ' . __LINE__ . ' " 行';
echo"<br>";
echo '该文件位于 " ' . __FILE__ . ' " ';
echo"<br>";
echo '该文件位于 " ' . __DIR__ . ' " ';
echo"<br>";
class Test{
public function doit(){
echo '函数名为:'.__FUNCTION__;
}
public function doitAgain(){
echo '函数名为:'.__METHOD__;
}
}
$obj = new Test();
$obj->doit();
echo '<br>';
$obj->doitAgain();
echo"<br>";
class test1 {
function _print() {
echo '类名为:' . __CLASS__ . "<br>";
echo '函数名为:' . __FUNCTION__ ;
}
}
$t = new test1();
$t->_print();
echo"<br>";
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}
$o = new MyHelloWorld();
$o->sayHello();
$o->sayWorld();
$o->sayExclamationMark();
echo"<br>";
echo '命名空间为:"', __NAMESPACE__, '"'; // 输出 "MyProject"
?>
7.命名空间
命名空间必须是程序脚本的第一条语句
PHP 命名空间可以解决以下两类问题:
- 用户编写的代码与PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲突。
- 为很长的标识符名称(通常是为了缓解第一类问题而定义的)创建一个别名(或简短)的名称,提高源代码的可读性。
7.1定义命名空间
- 将全局的非命名空间中的代码与命名空间中的代码组合在一起,只能使用大括号形式的语法。全局代码必须用一个不带名称的 namespace 语句加上大括号括起来
- 在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前。
<?php
declare(encoding='UTF-8'); //定义多个命名空间和不包含在命名空间中的代码
namespace MyProject {
const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */ }
}
namespace { // 全局代码
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}
?>
7.2子命名空间
与目录和文件的关系很像,PHP 命名空间也允许指定层次化的命名空间的名称。因此,命名空间的名字可以使用分层次的方式定义:
<?php
namespace MyProject\Sub\Level; //声明分层次的单个命名空间
const CONNECT_OK = 1;
class Connection { /* ... */ }
function Connect() { /* ... */ }
?>
上面的例子创建了常量 MyProject\Sub\Level\CONNECT_OK,类 MyProject\Sub\Level\Connection 和函数 MyProject\Sub\Level\Connect。
7.3命名空间的使用
PHP 命名空间中的类名可以通过三种方式引用:
- 非限定名称,或不包含前缀的类名称
- 限定名称,或包含前缀的名称
- 完全限定名称,或包含了全局前缀操作符的名称
<?php
namespace AA\BB;
function showinfo(){
echo __METHOD__.'<br>';
}
namespace CC;
function showinfo(){
echo __METHOD__.'<br>';
}
namespace AA;
function showinfo(){
echo __METHOD__.'<br>';
}
//非限定访问:用于访问当前空间中的成员,位于哪个命名空间下就访问哪个
showinfo();
//限定访问:只能访问当前所在空间的子空间中的成员
BB\showinfo();
//完全限定访问:可以访问其他所有空间的成员
\CC\showinfo();
?>
7.4命名空间和动态语言特征
动态访问命名空间的元素,PS:因为在动态的类名称、函数名称或常量名称中,限定名称和完全限定名称没有区别,因此其前导的反斜杠是不必要的。
test.php
<?php
class classname
{
function __construct()
{
echo __METHOD__."<br>";
}
}
function funcname()
{
echo __FUNCTION__."<br>";
}
const constname = "global";
?>
test1.php
<?php
namespace namespacename;
class classname
{
function __construct()
{
echo __METHOD__,"<br>";
}
}
function funcname()
{
echo __FUNCTION__,"<br>";
}
const constname = "namespaced";
include 'test.php';
$a = 'classname';
$obj = new $a; // 输出 classname::__construct
$b = 'funcname';
$b(); // 输出函数名
echo constant('constname'), "<br>"; // 输出 global
/* 如果使用双引号,使用方法为 "\\namespacename\\classname"*/
$a = '\namespacename\classname';
$obj = new $a; // 输出 namespacename\classname::__construct
$a = 'namespacename\classname';
$obj = new $a; // 输出 namespacename\classname::__construct
$b = 'namespacename\funcname';
$b(); // 输出 namespacename\funcname
$b = '\namespacename\funcname';
$b(); // 输出 namespacename\funcname
echo constant('\namespacename\constname'), "\n"; // 输出 namespaced
echo constant('namespacename\constname'), "\n"; // 输出 namespaced
?>
7.5namespace关键字和__NAMESPACE__常量
PHP支持两种抽象的访问当前命名空间内部元素的方法,NAMESPACE 魔术常量和namespace关键字。
1.常量__NAMESPACE__的值是包含当前命名空间名称的字符串。在全局的,不包括在任何命名空间中的代码,它包含一个空的字符串。
2.关键字 namespace 可用来显式访问当前命名空间或子命名空间中的元素。它等价于类中的 self 操作符。
<?php
namespace MyProject{
echo '"', __NAMESPACE__, '"','<br>'; // 输出 "MyProject"
}
namespace{
echo '"', __NAMESPACE__, '"','<br>';//输出 ""
}
<?php
namespace AA\BB;
function showinfo(){
echo __METHOD__.'<br>';
}
namespace AA;
function showinfo(){
echo __METHOD__.'<br>';
}
namespace\showinfo();
namespace\BB\showinfo();
?>
7.6使用命名空间:别名/导入
PHP 命名空间支持 有两种使用别名或导入方式:为类名称使用别名,或为命名空间名称使用别名。
<?php
namespace My\Full{
class Classname{
function __construct(){
echo __NAMESPACE__.'<br />';
}
}
}
namespace My\Full\NSname\subns{
function func(){
echo __NAMESPACE__.'<br />';
}
}
namespace FOO\bar{
const name = "test";
function say(){
echo __NAMESPACE__.'<br />';
}
}
namespace Foo{
class foo{
public function __construct(){
echo 'XingYun';
}
}
}
namespace foo{
use My\Full\Classname;
use My\Full\NSname;
use FOO\bar;
new Classname();// 实例化 My\Full\Classname 对象
NSname\subns\func();// 调用函数 My\Full\NSname\subns\func
bar\say();
echo constant('\FOO\bar\name').'<br>';
new namespace\foo();
}
?>
7.7使用命名空间:后备全局函数/常量
对于函数和常量来说,如果当前命名空间中不存在该函数或常量,PHP 会退而使用全局空间中的函数或常量。
<?php
namespace A\B\C;
const E_ERROR = 45;
function strlen($str)
{
return \strlen($str) - 1;
}
echo E_ERROR, "\n"; // 输出 "45"
echo INI_ALL, "\n"; // 输出 "7" - 使用全局常量 INI_ALL
echo strlen('hi'), "\n"; // 输出 "1"
if (is_array('hi')) { // 输出 "is not array"
echo "is array\n";
} else {
echo "is not array\n";
}
?>
7.8全局空间
PS:没研究出来,之后再看
<?php
namespace A\B\C;
/* 这个函数是 A\B\C\fopen */
function fopen() {
/* ... */
$f = \fopen(...); // 调用全局的fopen函数
return $f;
}
?>
7.9命名空间的顺序
名称解析遵循下列规则:
-
对完全限定名称的函数,类和常量的调用在编译时解析。例如 new \A\B 解析为类 A\B。
-
所有的非限定名称和限定名称(非完全限定名称)根据当前的导入规则在编译时进行转换。例如,如果命名空间 A\B\C 被导入为 C,那么对 C\D\e() 的调用就会被转换为 A\B\C\D\e()。
-
在命名空间内部,所有的没有根据导入规则转换的限定名称均会在其前面加上当前的命名空间名称。例如,在命名空间 A\B 内部调用 C\D\e(),则 C\D\e() 会被转换为 A\B\C\D\e() 。
-
非限定类名根据当前的导入规则在编译时转换(用全名代替短的导入名称)。例如,如果命名空间 A\B\C 导入为C,则 new C() 被转换为 new A\B\C() 。
-
在命名空间内部(例如A\B),对非限定名称的函数调用是在运行时解析的。例如对函数foo()的调用是这样解析的:
- 在当前命名空间中查找名为 A\B\foo() 的函数
- 尝试查找并调用 全局(global) 空间中的函数 foo()。
-
在命名空间(例如A\B)内部对非限定名称或限定名称类(非完全限定名称)的调用是在运行时解析的。下面是调用new C()及new D\E()的解析过程:
new C()的解析:
- 在当前命名空间中查找A\B\C类。
- 尝试自动装载类A\B\C。
new D\E()的解析:
- 在类名称前面加上当前命名空间名称变成:A\B\D\E,然后查找该类。
- 尝试自动装载类 A\B\D\E。
为了引用全局命名空间中的全局类,必须使用完全限定名称new \C()。
<?php namespace A; use B\D, C\E as F; // 函数调用 foo(); // 首先尝试调用定义在命名空间"A"中的函数foo() // 再尝试调用全局函数 "foo" \foo(); // 调用全局空间函数 "foo" my\foo(); // 调用定义在命名空间"A\my"中函数 "foo" F(); // 首先尝试调用定义在命名空间"A"中的函数 "F" // 再尝试调用全局函数 "F" // 类引用 new B(); // 创建命名空间 "A" 中定义的类 "B" 的一个对象 // 如果未找到,则尝试自动装载类 "A\B" new D(); // 使用导入规则,创建命名空间 "B" 中定义的类 "D" 的一个对象 // 如果未找到,则尝试自动装载类 "B\D" new F(); // 使用导入规则,创建命名空间 "C" 中定义的类 "E" 的一个对象 // 如果未找到,则尝试自动装载类 "C\E" new \B(); // 创建定义在全局空间中的类 "B" 的一个对象 // 如果未发现,则尝试自动装载类 "B" new \D(); // 创建定义在全局空间中的类 "D" 的一个对象 // 如果未发现,则尝试自动装载类 "D" new \F(); // 创建定义在全局空间中的类 "F" 的一个对象 // 如果未发现,则尝试自动装载类 "F" // 调用另一个命名空间中的静态方法或命名空间函数 B\foo(); // 调用命名空间 "A\B" 中函数 "foo" B::foo(); // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法 // 如果未找到类 "A\B" ,则尝试自动装载类 "A\B" D::foo(); // 使用导入规则,调用命名空间 "B" 中定义的类 "D" 的 "foo" 方法 // 如果类 "B\D" 未找到,则尝试自动装载类 "B\D" \B\foo(); // 调用命名空间 "B" 中的函数 "foo" \B::foo(); // 调用全局空间中的类 "B" 的 "foo" 方法 // 如果类 "B" 未找到,则尝试自动装载类 "B" // 当前命名空间中的静态方法或函数 A\B::foo(); // 调用命名空间 "A\A" 中定义的类 "B" 的 "foo" 方法 // 如果类 "A\A\B" 未找到,则尝试自动装载类 "A\A\B" \A\B::foo(); // 调用命名空间 "A" 中定义的类 "B" 的 "foo" 方法 // 如果类 "A\B" 未找到,则尝试自动装载类 "A\B" ?>
8.面向对象
- 类 − 定义了一件事物的抽象特点。类的定义包含了数据的形式以及对数据的操作。
- 对象 − 是类的实例。
- 成员变量 − 定义在类内部的变量。该变量的值对外是不可见的,但是可以通过成员函数访问,在类被实例化为对象后,该变量即可称为对象的属性。
- 成员函数 − 定义在类的内部,可用于访问对象的数据。
- 继承 − 继承性是子类自动共享父类数据结构和方法的机制,这是类之间的一种关系。在定义和实现一个类的时候,可以在一个已经存在的类的基础之上来进行,把这个已经存在的类所定义的内容作为自己的内容,并加入若干新的内容。
- 父类 − 一个类被其他类继承,可将该类称为父类,或基类,或超类。
- 子类 − 一个类继承其他类称为子类,也可称为派生类。
- 多态 − 多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
- 重载 − 简单说,就是函数或者方法有同样的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
- 抽象性 − 抽象性是指将具有一致的数据结构(属性)和行为(操作)的对象抽象成类。一个类就是这样一种抽象,它反映了与应用有关的重要性质,而忽略其他一些无关内容。任何类的划分都是主观的,但必须与具体的应用有关。
- 封装 − 封装是指将现实世界中存在的某个客体的属性与行为绑定在一起,并放置在一个逻辑单元内。
- 构造函数 − 主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。
- 析构函数 − 析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做"清理善后" 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
8.1类定义
class phpclass{
//主体框架:class 类的名字
}
8.2创建对象
类创建后,我们可以使用 new 运算符来实例化该类的对象:
<?php
class Site {
/* 成员变量 */
var $url;
var $title;
/* 成员函数 */
function setUrl($par){
$this->url = $par;
}
function getUrl(){
echo $this->url . PHP_EOL;
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title . PHP_EOL;
}
}
$runoob = new Site;
$taobao = new Site;
$google = new Site;
// 调用成员函数,设置标题和URL
$runoob->setTitle( "菜鸟教程" );
$taobao->setTitle( "淘宝" );
$google->setTitle( "Google 搜索" );
$runoob->setUrl( 'www.runoob' );
$taobao->setUrl( 'www.taobao' );
$google->setUrl( 'www.google' );
// 调用成员函数,获取标题和URL
$runoob->getTitle();echo '<br>';
$runoob->getUrl();echo '<br>';
$taobao->getTitle();echo '<br>';
$taobao->getUrl();echo '<br>';
$google->getTitle();echo '<br>';
$google->getUrl();echo '<br>';
?>
8.3构造函数
构造函数是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值,在创建对象的语句中与 new 运算符一起使用。
<?php
class Site {
/* 成员变量 */
var $url;
var $title;
function _construct($par1,$par2){
$this->url = $par1;
$this->title = $par2;
}
/* 成员函数 */
function setUrl($par){
$this->url = $par;
}
function getUrl(){
echo $this->url . PHP_EOL;
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title . PHP_EOL;
}
}
$runoob = new Site;
$taobao = new Site;
$google = new Site;
// 调用成员函数,设置标题和URL
$runoob->setTitle( "菜鸟教程" );
$taobao->setTitle( "淘宝" );
$google->setTitle( "Google 搜索" );
$runoob->setUrl( 'www.runoob' );
$taobao->setUrl( 'www.taobao' );
$google->setUrl( 'www.google' );
// 调用成员函数,获取标题和URL
$runoob->getTitle();echo '<br>';
$runoob->getUrl();echo '<br>';
$taobao->getTitle();echo '<br>';
$taobao->getUrl();echo '<br>';
$google->getTitle();echo '<br>';
$google->getUrl();echo '<br>';
?>
8.4析构函数
析构函数(destructor) 与构造函数相反,当对象结束其生命周期时(例如对象所在的函数已调用完毕),系统自动执行析构函数。
<?php
class MyDestructableClass {
function __construct() {
print "构造函数";
$this->name = "MyDestructableClass";
print '<br>';
}
function __destruct() {
print "销毁 " . $this->name . "\n";
}
}
new MyDestructableClass();
?>
8.5继承
PHP 使用关键字 extends 来继承一个类,PHP 不支持多继承。
<?php
class a
{
function printItem($string)
{
echo 'a: ' . $string . '<br>';
}
function printPHP()
{
echo 'PHP is great.' . '<br>';
}
}
class b extends a
{
function printItem($string)
{
echo 'a: ' . $string . '<br>';
}
}
$a = new a();
$b = new b();
$a->printItem('233');
$a->printPHP();
$b->printItem('233');
$b->printPHP();
?>
8.6方法重写
如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
<?php
class a
{
function printItem($string)
{
echo 'a: ' . $string . '<br>';
}
function printPHP()
{
echo 'PHP is great.' . '<br>';
}
}
class b extends a
{
function printItem($string)
{
echo 'b: ' . $string . '<br>';
return $string;
}
}
$a = new a();
$b = new b();
$a->printItem('233');
$a->printPHP();
$b->printItem('233');
$b->printPHP();
?>
8.7访问控制
PHP 对属性或方法的访问控制,是通过在前面添加关键字 public(公有),protected(受保护)或 private(私有)来实现的。
- **public(公有):**公有的类成员可以在任何地方被访问。
- **protected(受保护):**受保护的类成员则可以被其自身以及其子类和父类访问。
- **private(私有):**私有的类成员则只能被其定义所在的类访问。
8.7.1属性的访问控制
<?php
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // 这行能被正常执行
echo $obj->protected; // 这行会产生一个致命错误
echo $obj->private; // 这行也会产生一个致命错误
$obj->printHello(); // 输出 Public、Protected 和 Private
两个错误
Uncaught Error: Cannot access protected property MyClass::$protected
Uncaught Error: Cannot access private property MyClass::$private
8.7.2方法的访问控制
类中的方法可以被定义为公有,私有或受保护。如果没有设置这些关键字,则该方法默认为公有。
<?php
class MyClass
{
// 声明一个公有的构造函数
public function __construct() { }
// 声明一个公有的方法
public function MyPublic() {
echo '公有<br>';
}
// 声明一个受保护的方法
protected function MyProtected() {
echo '保护<br>';
}
// 声明一个私有的方法
private function MyPrivate() {
echo '私有<br>';
}
// 此方法为公有
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
$myclass = new MyClass;
$myclass->MyPublic(); // 这行能被正常执行
//$myclass->MyProtected(); // 这行会产生一个致命错误
//$myclass->MyPrivate(); // 这行会产生一个致命错误
$myclass->Foo(); // 公有,受保护,私有都可以执行
?>
两个错误
Uncaught Error: Call to protected method MyClass::MyProtected()
Uncaught Error: Call to private method MyClass::MyPrivate()
8.8接口(API?)
使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。
接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。
接口中定义的所有方法都必须是公有,这是接口的特性。
要实现一个接口,使用 implements 操作符。类中必须实现接口中定义的所有方法,否则会报一个致命错误。类可以实现多个接口,用逗号来分隔多个接口的名称。
<?php
interface Fruit
{
const MAX_WEIGHT = 5; //此处不用声明,就是一个静态常量
function setName($name);
function getName();
}
//实现接口
class Apple implements Fruit
{
private $name;
function getName() {
return $this->name;
}
function setName($_name) {
$this->name = $_name;
}
}
$apple = new Apple(); //创建对象
$apple->setName("苹果");
echo "创建了一个" . $apple->getName();
echo "<br />";
echo "MAX_GRADE is " . Apple::MAX_WEIGHT; //静态常量
?>
8.9常量
可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。
常量的值必须是一个定值,不能是变量,类属性,数学运算的结果或函数调用。
<?php
class MyClass
{
const constant = '常量值';
function showConstant() {
echo self::constant . '<br>';
}
}
echo MyClass::constant . '<br>';
$classname = "MyClass";
echo $classname::constant . '<br>';
$class = new MyClass();
$class->showConstant();
echo $class::constant . '<br>';
?>
8.10抽象类
任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。
定义为抽象的类不能被实例化。
被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。
继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。
<?php
abstract class AbstractClass
{
// 强制要求子类定义这些方法
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// 普通方法(非抽象方法)
public function printOut() {
print $this->getValue() . '<br>';
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') . '<br>';
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') . '<br>';
?>
8.11Static 关键字
声明类属性或方法为 static(静态),就可以不实例化类而直接访问。
静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。
由于静态方法不需要通过对象即可调用,所以伪变量 $this 在静态方法中不可用。
静态属性不可以由对象通过 -> 操作符来访问。
<?php
class Foo {
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
print Foo::$my_static . '<br>';
$foo = new Foo();
print $foo->staticValue() . '<br>';
?>
8.12Final 关键字
final 关键字。如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called" . PHP_EOL;
}
final public function moreTesting() {
echo "BaseClass::moreTesting() called" . PHP_EOL;
}
}
class ChildClass extends BaseClass {
public function moreTesting() {
echo "ChildClass::moreTesting() called" . PHP_EOL;
}
}
// 方法声明final报错信息 Fatal error: Cannot override final method BaseClass::moreTesting()
// 类声明final Fatal error: Class ChildClass may not inherit from final class (BaseClass)
?>
8.13调用父类构造方法
PHP 不会在子类的构造方法中自动的调用父类的构造方法。要执行父类的构造方法,需要在子类的构造方法中调用 parent::__construct()
<?php
class BaseClass {
function __construct() {
print "BaseClass 类中构造方法" . '<br>';
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct(); // 子类构造方法不能自动调用父类的构造方法
print "SubClass 类中构造方法" . '<br>';
}
}
class OtherSubClass extends BaseClass {
// 继承 BaseClass 的构造方法
}
// 调用 BaseClass 构造方法
$obj = new BaseClass();
// 调用 BaseClass、SubClass 构造方法
$obj = new SubClass();
// 调用 BaseClass 构造方法
$obj = new OtherSubClass();
?>
更多推荐
PHP学习笔记(二)——行云博客
发布评论