面向对象学习笔记整理
对象类型在内存中的分配
1:内存结构
栈空间段(后进先出):空间小被CPU访问速度快,用于存放程序中的临时变量,方便用于保存和恢复调用现场,主要存放占用空间小的数据类型(整型,bool型)
堆空间段(先进先出):存放程序运行中动态分配的内存段,存储占用空间较大的数据类型(数组,资源,对象)
数据段:存储已经初始化的全局变量,换句话就是说存储静态分布的变量。
代码段:代码段需要在运行时防止被非法修改,值允许读取操作。(函数)
- $student = new Person();
a:实例化对象$student存储在栈内存段中
b:类Person存储在堆内存中
2:使用final标识的类不能被继承;在类中使用final标识的成员方法,在子类方法不能被覆盖。
3:类的静态属性类似于全局变量
访问方式1 类名:静态成员属性/方法名
访问方式2 self: 静态成员属性/方法名
4:单态设计模式是指在OOP中一个类只能有一个实例对象存在。
5:将类中的成员属性定义为常量,只能使用const关键字,在类中声明为常量的属性为只读不能重新赋值。常量在声明时一定要赋初值。访问通过self
6:在PHP中,同一个类中只能声明一个构造方法,默认是public访问
7:析构方法是在对象呗销毁前最后调用的一个方法。当堆内存中的对象失去访问它的引用时,就不可再被访问。析构方法不能带有任何参数
8:魔术方法__set()的作用是在程序运行过程中为私有属性设置值,不需要返回值。该方法需要两个参数,$propertyName与$propertyValue,分别对应属性名誉属性值。代码详见__set.php
9:魔术方法__get()的作用是程序在执行过程中,通过这个魔术方法获取私有属性的值。该方法需要一个必填参数$propertyName,该方法执行结果会返回一个值。代码详见__get.php
10:魔术方法__isset() 方法用于检测私有属性值是否被设定。 如果对象里面成员是公有的,可以直接使用 isset() 函数。如果是私有的成员属性,那就需要在类里面加上一个 __isset() 方法。代码详见__isset.php
11:魔术方法__unset() 方法用于删除私有属性。 如果对象里面成员属性是公有的,可以直接使用unset() 函数。如果是私有的成员属性,那就需要在类里面加上一个 __unset() 方法。
12:OOP中访问控制符的区别
范围 | public | protected | private |
---|---|---|---|
本类 | Y | Y | Y |
子类 | Y | Y | N |
外部 | Y | N | N |
在类继承中可以对 public 和 protected 进行重定义,但 private 而不能
13:OOP中final关键字的使用
final关键字可以加在类名前或是类中的方法名前,类中的成员属性不能使用final。
使用final标识的类名不能被继承。
使用final标识的方法不能被重写。
14:OOP中static关键字使用
使用static关键字可以将类中的成员属性与成员方法标识为静态,表示唯一存在。
类中的静态成员使用类名直接访问。
在类中的成员方法中,可以使用self关键字来访问其它静态成员。//静态成员属于类而不属于对象所以不用$this。
示例代码static.php
14:单态设计模式--一个类只能存在一份对象
15:CONST关键字--面向对象中常量的定义,只读,类中成员方法可以使用self来访问,外部访问时className::常量名
16:instanceof判断一个对象是否是某个类的实例化
17:对象克隆Clone
根据现有的对象克隆出一个一幕一样的对象,原对象和克隆的对象完全一致,二者相互对立,互不影响。
<?php
class Program{
private $os;
private $server;
private $language;
private $database;
public function __construct($os="linux", $server="apache", $language="php", $database="MongoDB"){
$this->os = $os;
$this->server =$server;
$this->language =$language;
$this->database =$database;
}
public function info(){
echo "操作系统:".$this->os."<br/>";
echo "Web服务器:".$this->server."<br/>";
echo "编程语言:".$this->language."<br/>";
echo "数据库软件:".$this->database."<hr/>";
}
}
$coder1 = new Program("Ubuntu");
$coder2 = Clone $coder1;
$coder2->info();
?>
如果需要对克隆后的副本成员属性重新赋值,可以使用魔术方法__clone,该方法不需要任何参数,该方法包含了$this与$that两个对象的引用。其中$this是clone对象的引用,$that是原始对象的引用。
<?php
class Program{
private $os;
private $server;
private $language;
private $database;
public function __construct($os="linux", $server="apache", $language="php", $database="MongoDB"){
$this->os = $os;
$this->server =$server;
$this->language =$language;
$this->database =$database;
}
public function __clone(){
$this->language = "现在已将语言由".@$this->language."替换为Python";
}
public function info(){
echo "操作系统:".$this->os."<br/>";
echo "Web服务器:".$this->server."<br/>";
echo "编程语言:".$this->language."<br/>";
echo "数据库软件:".$this->database."<hr/>";
}
}
$coder1 = new Program("Ubuntu");
$coder2 = Clone $coder1;
$coder2->info();
?>
18:魔术方法__String()
魔术方法__toString() 方法用于一个类被当成字符串时应怎样回应。例如 echo $obj; 应该显示些什么。此方法必须返回一个字符串,否则将发出一条 E_RECOVERABLE_ERROR 级别的致命错误。
<?php
class Program{
public $language;
public function __construct($language,$database="mysql"){
$this->language = $language;
$this->database = $database;
}
public function __toString(){
return $this->language."-".$this->database;
}
}
$code = new Program("PHP");
echo $code; //这里自动调用魔术方法__toString()
?>
19:OOP中访问一个不存在的方法时如果不出意外是会报错的,要怎样才能让他不报错呢?下面魔术方法__Call()。在调用对象中不存在的方法时会自动调用该方法。该方法需要两个参数$propertyName和$args。代码示例如下。
<?php
class Person{
public $language;
public $database;
public function __construct($language="php", $database="mysql"){
$this->language = $language;
$this->database = $database;
}
public function __Call($propertyName, $args){
echo "你调用的方法是".$propertyName."<br/>";
echo "方法的参数是<pre>";
print_r($args);
echo "<br/>不过该方法并不存在!";
}
}
$code = new Person;
$code->info("php","linux");
?>
20:类的自动调用
//autoload.php
<?php
function __autoload($className){
include(strtolower($className).".class.php");
}
$dd = new name(); //自动调用到name.class
$dd ->getInfo(); //output 雨醉风尘
?>
```
```
//name.class.php
<?php
class name{
public function getInfo(){
echo "雨醉风尘";
}
}
?>
```
22:对象的串行化serialize()与反串行化unserialize()
```
<?php
class Person{
private $name;
private $age;
private $sex;
function __construct($name="User", $age=20, $sex="男"){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
public function info(){
echo "这是".$this->name."的个人信息<br/>";
echo "年龄:".$this->age."<br/>";
echo "性别:".$this->sex."<br/>";
}
}
$dd = new Person("雨醉风尘",22);
$dd_string = serialize($dd);
echo $dd_string;
//O:6:"Person":3:{s:12:"Personname";s:12:"雨醉风尘";s:11:"Personage";i:22;s:11:"Personsex";s:3:"男";}
echo "<hr/>";
$dd_un = unserialize($dd_string);
$dd_un->info();
?>
```
23:抽象方法是指没有方法体的方法,声明一个方法为抽象方法时,使用关键字abstract修饰。举例**abstract function test();**
24:抽象类是指包含抽象方法的类,不能被直接实例化,通过继承实现抽象类中的抽象方法。子类继承抽象类后必须全部实现抽象类中的抽象方法。
25:接口是指抽象类中所有的方法都是抽象方法的类,用interface修饰,接口中的方法可以不适用abstract修饰。接口的实现使用关键字implements
26:接口中定义的所有方法都必须是公有,这是接口的特性。
27:类可以实现多个接口,用逗号来分隔多个接口的名称。