PHP OOP

PHP 使用了一段时间, 从对OOP的不了解, 再到使用, 觉得挺好, 特写下

OOP并不是为了面向对象而面向对象, 而是为了达到代码的重用性、灵活性、扩展性

对象和类

从先有对象才有人类, 这个来说, 有点不合理的合理

类:具有相同属性的一组对象的集合
对象:类实例化之后就是对象
看下一般的类的定义

name = $name;
$this->age = $age;
$this->sex = $sex;
}
// 析构函数
function __destruct(){
echo "byebye\n";
}
// 成员方法
function eat(){
echo "my name is ". $this->name;
}
function sleep(){
echo "i am sleeping";
}
}
// 类的实例化
$jaime = new Person("jaime", "man", 24);
$jaime->eat();

?>
保存为index.php, 在命令窗口输入

$ php index.php
my name is jaime
byebye
如果

$jaime = new Person("jaime", "man", 24);
改为

$jaime = new Person("jaime", "man");
则会触发异常, 会有以下的消息出来, 包括错误信息, 错误行数, 和堆栈信息

$ php index.php

Fatal error: Uncaught exception 'Exception' with message 'must set name , sex, age' in E:\net\index.php on line 15

Exception: must set name , sex, age in E:\net\index.php on line 15

Call Stack:
0.0025 242440 1. {main}() E:\net\index.php:0
0.0025 243016 2. Person->__construct() E:\net\index.php:30

对象和内存

说点理论上的东西吧,

内存的分类:

堆(heap): 不可直接存取, 存储占有空间很大的数据类型的数据

栈(stack): 可以直接存取, 存储占用相同空间长度并且占用空间小的数据, 如存放局部变量,函数参数,当前状态,函数调用信息等

$jaime = new Person("jaime", "man", 24);
$jaime是存放在栈内存里面的引用变量, 即存储在堆中对象的首地址, 一个指针

new Person 实例化出来的对象是存放在堆内存里面的, 是真正的对象实例

对象和成员

变量,方法(内部成员函数)的前缀:

private: 私有成员

public:  公有成员(外部接口),没有加修饰, 默认就是public

protected: 保护型成员, 继承的类可以调用

访问private修饰的变量

Fatal error: Cannot access private property Person::$name in E:\net\index.php on line 36
如果想访问private, protected修饰的成员:

  1. 把private改为public

  2. 使用__get(), ___set()魔术方法, 但是还是写出代码来看看根据实际情况使用

name = $name;
$this->age = $age;
$this->sex = $sex;
}
function __destruct(){
echo "byebye\n";
}

function eat(){    echo "my name is ". $this->name."\n";}function sleep(){    echo "i am sleeping\n";}function __get($property_name){    $access_array = ['age','name'];// 只允许访问age,name两个私有成员    if(in_array($property_name, $access_array)){        return ($this->$property_name);    }    else{        return NULL;    }}function __set($property_name, $value){    $access_array = ['age'];// 只允许访问age这个私有成员    if(in_array($property_name, $access_array)){        $this->$property_name = $value;    }}

}

$jaime = new Person("jaime", "man", 24);
$jaime->eat();
echo ($jaime->age === NULL)? "NULL":$jaime->age;
echo "\n";
echo ($jaime->sex === NULL)? "NULL":$jaime->sex;
$jaime->age = 80;
echo "\n";
echo ($jaime->age === NULL)? "NULL":$jaime->age;
echo "\n";
$jaime->name = "lll";
echo ($jaime->name === NULL)? "NULL":$jaime->name;
echo "\n";
?>
执行结果如下

$ php index.php
my name is jaime
24
NULL
80
jaime
byebye

类的继承

name = $name;
$this->age = $age;
$this->sex = $sex;
}
function __destruct(){
echo "byebye\n";
}

function hello(){    echo "my name is ". $this->name."\n";}function sleep(){    echo "i am sleeping\n";}

}

class Student extends Person
{
private $school;

function __construct($name, $sex, $age, $school){    // 调用父类方法, 构造函数    parent::__construct($name, $sex, $age);    $this->school = $school;}// 重载了父类方法function sleep(){    echo "afternoon sleep\n";    // 调用父类方法    parent::sleep();}

}

$jaime = new Student("jaime", "man", 24,"zh");
$jaime->hello();
$jaime->sleep();
?>
执行后输出

$ php index.php
my name is jaime
afternoon sleep
i am sleeping

byebye
调用父类的方法需要用parent

静态成员和常量

no bb, show code

show();
?>
结果

$ php is.php
China
en
I live in China
I live in American
xxxAmerican en
类的静态变量,类似于全局变量,能够被所有类的实例共享,类的静态方法也是一样的,类似于全局函数, 静态成员被这个类的每个实例对象所共享

访问静态方法访问静态成员不能用$this, 需要用self

$this表示了此方法的对象

'self'表示此静态方法所在的类, self::成员

抽象方法和抽象类

什么叫抽象?不具体的就叫抽象! so

抽象方法 : 类里面没有具体方法体的方法(其实就是不具体的方法)

抽象类: 含有抽象方法的类,

抽象类不能实例化会报错"Cannot instantiate abstract class ", 有点像C里面的函数声明, 仅仅只是一个声明

fun1();
(new demo0())->fun2();
(new demo0())->fun3();
?>

接口interface

什么是接口?

如果一个内里面所有的方法都是抽象方法, 我们可以把声明方式换为接口

接口是一种特殊的抽象类, 接口不能包含成员的任何代码,只定义成员身。接口成员的具体代码由实现接口的类提供

接口的继承

接口的实现

fun1();
(new demo())->fun2();
(new demo())->fun3();
(new demo())->fun4();
?>

一个类实现多个接口

一个人要遵守的法律不止一步吧, 所以see code

fun1();
(new demo())->fun2();
(new demo())->fun3();
(new demo())->fun4();
?>
你娶了你老婆你得对她的家人负责吧, 就像下面

// 使用extends继承一个类,使用implements实现多个接口
class demo extend AbstractClass implements One, Two{
......
// 所有接口中的方法都要实现才可以实例化对象
}

Trait

trait 是一种代码复用的方法, 同抽象类一样无法实例化

see code

word = $word;
}
public function sayHello() {
echo 'Hello '.$this->word."\n";
}
}

trait A {
public function sayHello() {
// 会调用继承基类中的方法
parent::sayHello();
}
}

trait B {
public function say(){
echo "this is a demo B";
}
}

class Demo extends Base {
// 使用use来引用trait
use A, B;
// 取消注释,当前类中的方法会覆盖trait方法,而trait方法又覆盖了基类中的方法
//public function sayHello(){echo "say hello";}
}

(new Demo('php'))->sayHello();
(new Demo('php'))->say();
?>

魔术方法

isset()/ unset()

isset() 检测变量是否设置,返回true/false

unset() 销毁指定的变量, 在销毁静态变量, 全局变量时要注意

__toString()

foo = $foo;
}
function toString(){
return $this->foo.
FUNCTION__;
}
}

echo (new demo("jaime"));
?>
输出为

$ php ia.php
jaime__toString

__call()

调用不存在的方法就会自动调用__call()

test(1,2,3);
// 程序不会执行到这里
echo "go on";
?>
会报错

$ php ia.php
Fatal error: Call to undefined method demo::test() in E:\net\ia.php on line 5
Call Stack:
0.0000 235232 1. {main}() E:\net\ia.php:0
加上__call

test(1,2,3);
// 程序继续执行
echo "go on";
?>
结果

$ php ia.php
call function is test
Array
(
[0] => 1
[1] => 2
[2] => 3
)
not exist
go on
下面一段代码摘自ThinkPHP>controller.class.php

/  * 魔术方法 有不存在的操作的时候执行 * @access public * @param string $method 方法名 * @param array $args 参数 * @return mixed */public function __call($method,$args) {    if( 0 === strcasecmp($method,ACTION_NAME.C('ACTION_SUFFIX'))) {        if(method_exists($this,'_empty')) {            // 如果定义了_empty操作 则调用            $this->_empty($method,$args);        }else{            E(L('_ERROR_ACTION_').':'.ACTION_NAME);        }    }else{        E(__CLASS__.':'.$method.L('_METHOD_NOT_EXIST_'));        return;    }}

__autoload()

它会在试图使用尚未被定义的类时自动调用,通过调用此函数,脚本引擎在 PHP 出错失败前有了最后一个机会加载所需的类

定义一个类,取名为Demo.class.php

再建立一个文件index.php

sayHello();
?>
很多的框架都利用这个函数实现 类文件的自动加载 ,下面是DiscuzX2.5的实现方式

__clone()

复制对象

serialize(), sleep(), wakeup()

对象序列化

参考:

  1. 《细说PHP 》 兄弟连

  2. 《PHP手册》

  3. 《php面向对象(OOP)编程完全教程》

关键字:php, oop

版权声明

本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处。如若内容有涉嫌抄袭侵权/违法违规/事实不符,请点击 举报 进行投诉反馈!

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部