PHP面向对象总结

<?php

Header("Content-type:text/html;charset=utf-8");

/*********************************

《关于PHP面向对象的总结》

**********************************

前言:

1.其实魔术方法也是方法是函数,跟前面讲的函数一样,只不过在类里面有

$this->name这样的东西,他就是类的成员属性,他可以在这个类的任意位置出现。

有可能这个会扰乱你的思路,你只需分分辨清楚就行了,既然都是

函数都道理都是一样的,有的是有计算功能的,有的有返回值的你用完函数后打印出来,

或者你不打印,在函数里面不用return 用输出都行。

2.$this可以理解为好比是对象的“引用”,我们知道对象访问他的成员属性和成员方法时只能用引用来访问

$this->name;

$this->say();

3.在类中某个成员属性如果在构造函数中不传入的话,在外部检测不到这个成员属性。

4.$class->nage 这个东西如果单独写,除了$this,他就是一个变量,你可以先赋值在输出试试,

5.魔术方法是在我们操作对象的时候自动运行,我们不确定他什么时候运行,但是他会自动运行。

6.类直接访问(不用创建对象)方法Person::tell();如果单纯的输入有值,如果里面有$this->什么的,就会报错了。

一.魔术方法

__construct()

__destruct()

__set()

__get()

__isset()

__unset()

__call()

__toString()

__autoload()

__sleep()

__wakeup()

__clone()

自动加载类方法

__autoload()

对象串行化方法

serialize()

unserialize()

二.常用的关键字和修饰字

var

public

protected

private

new

extends

final

static

const

instanceof

clone

abstract

interface

implements

三.单例模式

四.关于多态性

/

1.构造函数__construct()

构造函数可以接受参数,能够在创建对象时赋值给对象属性

构造函数可以调用类方法或其他函数

构造函数可以调用其他类的构造函数

<?php
class Person{
    private $name;
    private $age;
    private $sex;

    public function __construct($name,$age,$sex){
        $this->name=$name;
        $this->age=$age;
        $this->sex=$sex;
        $this->run($name);
    }
    private function run(){
        echo $this->name."在跑步";
    }
    public function say(){
        echo $this->name."在说话";
    }
    //下面这个是一个带参数
    public function say1($name){
        echo $name."在说话";
    }

}
$person = new Person("东方不败",18,‘不详‘);
$person->say();
$person->say1("nihao");
?>

调用父类构造函数,调用其他类的构造函数:

public function __constuct(){
parent::__constuct();
classname::__construct();
}

如果想要依次调用几个父类的构造函数,可以使用类名直接调用构造函数

2.析构函数__destuct()

这个主要是对象在销毁时自动调用的函数,一个对象在数去引用时,会自动销毁。

$a=$b=$c=new Person();

$a = null;

unset($b);

一个对象三个引用,失去了两个还有一个,程序加载完成后会自动销毁最后一个。

3.赋值函数__set()

__set( $property, $value ) 给一个未定义的成员属性赋值时调用,(私有成员)

4.取值函数__get()

__get( $property ) 获取成员属性的值(私有成员)

先可以判定下是否有这个成员

return isset($this->$property) ? $this->$property : null;

class Person{
    private $name;
    private $age;
    private $sex;
    public function __construct($name,$age,$sex){
        $this->name=$name;
        $this->age=$age;
        $this->sex=$sex;
        $this->run();
    }
    private function run(){
        echo $this->name."在跑步".$this->age;
    }
    public function say(){
        echo $this->name."在说话";
    }
    public function say1($name){
        echo $name."在说话";
    }
    public function __set($field,$value){
        if($field=="age"){
            if($value>200){
                // return "非法数据";
                $value="非法数据";
            }
        }
        $this->$field=$value;
    }
    public function __get($field){
        return $this->$field;
    }
}
$person = new Person("东方不败",210,‘不详‘);
$person->say();
// $person->run();
$person->say1("nihao");
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$person->age=220;
echo $person->age;

5.__isset()方法用于检测私有属性值是否被设定。

如果对象里面成员是公有的,可以直接使用 isset() 函数。如果是私有的成员属性,

那就需要在类里面加上一个 __isset() 方法,然后再使用isset()函数如下

public function __isset($property_name)

{

return isset($this->$property_name);

}

这样当在类外部使用 isset() 函数来测定对象里面的私有成员是否被设定时,就会自动调用 __isset() 方法来检测。

6.__unset()方法用于删除私有属性。

同 isset() 函数一样,unset() 函数只能删除对象的公有成员属性,当要删除对象内部的私有成员属性时,

需要使用__unset() 方法:

public function __unset($property_name)

{

unset($this->$property_name);

}

7.__call() 方法用于监视错误的方法调用。

为了避免当调用的方法不存在时产生错误,可以使用 __call() 方法来避免。该方法在调用的方法

不存在时会自动调用,程序仍会继续执行下去。语法:

public function __call($function_name, $arguments)

{

......

}

该方法有两个参数,

第一个参数 $function_name 会自动接收不存在的方法名。

第二个 $args 则以数组的方式接收不存在的方法的多个参数。

8.__toString()方法用来输出对象的引用

这个方法也是一样自动被调用的,是在 直接输出对象引用时自动调用的, 前面我们讲过对象引用是一个指针,

比如说:“$p=new Person()”中,$p 就是一个引用,我们不能使用echo 直接输出$p,这样会输出"Catchable fatal

error: Object of class Person could not be converted to string"这样的错误,如果你在类里面定义

了"__toString()"方法,在直接输出对象引用的时候,就不会产生错误,而是自动调用了 "__toString()"方法,

输出"__toString()"方法中返回的字符,所以"__toString()"方法一定 要有个返回值(return 语句)。

9.__autoload()方法用于自动加载其他文件中的类。

这个方法是唯一一个不在类中写的方法。

function __autoload($classname){

include_once ucfirst($classname)."Controller.php";

}

10.__sleep()方法是对象在序列化时执行的方法

注意了,对象在序列化后里面保存的只是他的属性(初始化的时候赋值了),函数和方法都是类的,不是对象的。这点要明确

11.__wakeup()方法是对象在反序列化时执行的方法.

在wake.php中

class db {
    private $host;
    private $user;
    private $pwd;
    private $dbname;
    private $mysqli;
    function __construct($host, $user, $pwd, $dbname) {
        $this->host = $host;
        $this->user = $user;
        $this->pwd = $pwd;
        $this->dbname = $dbname;
        $this->db();
    }
    function db() {
        $this->mysqli = new mysqli ( $this->host, $this->user, $this->pwd, $this->dbname );
    }
    function select() {
        $this->mysqli->query("SET CHARSET GBK");
        $sql = "SELECT * FROM ams_archives_rs LIMIT 0,4";
        $result = $this->mysqli
            ->query ( $sql );
        $rows = array ();
        while ( $row = $result->fetch_assoc () ) {
            $rows [] = $row;
        }
        ECHO "<PRE>";
        print_r ( $rows );
    }
    function __sleep(){
        return array_keys(get_object_vars($this));
    }
    function __wakeup(){
        $this->db();
    }
}
session_start();
$chanel = new db("localhost",‘root‘,‘admin888‘,‘ams‘);
//$chanel->select();
$_SESSION[‘channel_obj‘] = serialize($chanel);

在wakeupa.php中

session_start();
include ‘wakeup.php‘;
$channel_obj=unserialize($_SESSION[‘channel_obj‘]);
$channel_obj->select();
//如果在59.php中不写上__wakeup()方法会连接不上
11.__clone()这个使用关键字clone时自动运行的方法
public function __clone(){
    $this->class=2;
}
$person1=clone $person;
echo $person1->class;

二、这几个关键字我们挑选几个不常用的看看

1.const

他在类的内部使用的方法如下

self::常量名大写;

他在类的外部使用方法

类名::常量名大写;

2.extends 英文extend的第三人称单数是扩展继承的意思

3.final

可以修饰类和方法

修饰类,这个类不能被继承

修饰方法,这个方法不能被重写

4.static

翻译中文是静态的意思

用来修饰成员属性和方法

如果用来修饰成员属性,初始化后的所有对象都是共用这个成员属性。

他在类的内部使用方法如下

public function getName(){
    //return 类名::静态变量;
    //return self::静态变量;
    //return Person::$name;
    return self::$name;
}
public function setName($val){
    Person::$name=$val;
    //self::$name=$val;
}

$p->setName(‘东方不败‘);

//这里设置后所有的对象name都是东方不败了

他在类的外部使用的方法如下

Person::$name;//只能用类名::方法名

如果是用来修饰成员方法,他就不能访问非静态成员,因为非静态的成员必须用对象的引用来访问。

因此,用static修饰的方法里面就一定不使用非静态成员

5.instanceof

这个是用来判断一个对象是不是某个类实例化出来的

$p=new Person();

echo intval($p instanceof Person);

//还有一个函数也可以

echo intval(is_a($p,‘Person‘);//PHP官方不建议使用

还有一个函数是用来判断一个对象是不是某个类的子类实例化出来的(父亲级别)

is_subclass_of($p,‘Pseson‘);

6.abstract

中文意思是抽象的意思

这个关键字既可以修饰类也可以修饰方法

关于抽象方法:没有方法体的方法称作抽象方法,注意在类中声明抽象方法必须有abstract修饰

function fun();

关于抽象类:如果一个类中有abstract修饰的方法那么这个类就是抽象类

abstract class Person{

abstract function fun();

}

抽象类是为了规定一些共性的成员,一般是给了N个抽象类,抽象类自己不

被实例化,必须由子类继承过来(所以子类就不能再是抽象类了,而且非抽象方法和成员属性的访问

权限也就必须得protected和public),而且子类必须逐一实现这N个抽象方法;而且实现的方法必须

是public 或者不写;

7.interface

中文意思为接口

PHP是单继承,每个类只能继承一个父类

他是一种特殊的类,

接口里面的成员必须全是public权限,

接口里面的方法全都是抽象方法,并且不能用abstract修饰,

接口里的成员属性只能是常量(const NAME=‘hby‘);

可以写另外一个接口来继承(extends)一个接口,用来扩展里面的方法。

可以写一个抽象类来实现(implements)一个接口,用来实现里面的部分方法

可以写一个普通类来实现(implements)一个接口,用来实现里面的全部方法

一个类可以同时继承父类还实现N个接口.

class 类名 extends 父类名 implements 接口1,接口2,...接口n{

//实现所有接口中的抽象方法;

}

三、单例模式

网上说的意思归结到一点就是:让一个类只有一个实例.

如何做到呢?

1.前面学过,每次用 new 类名 的方式,就可以创建一个对象。我们必须禁止

外部程序用 new 类名的方式来创建多个实例。

解决办法是:我们将构造函数设置成 private ,让构造函数只能在内部被调用,

而外部不能调用。这样,这个类就不能被外部用 new 的方式建立多个实例了。

class A{

private function __construct(){}

}

$a = new A();

2.我们已经禁止外部用new实例化这个类,我们改如何让用户访问这个类呢?前门堵了,

我们需要给用户留个后门。

解决办法是:static 修饰的方法,可以不经实例化一个类就可以直接访问这个方法。

class A{
    private function __construct(){}
    static function getClassA(){
        return "这里是后门,可以通过这里进入类内部..";
    }
}
echo A::getClassA();

3.虽然我们已经进入类内部,但我们要的是这个类的唯一实例?先不管别的,

我们先需要一个实例。通过这个static的方法返回这个实例,如何做呢?

下面的例子我们确实返回了A类的实例,但注意两次执行返回的不是同一个实例。

class A{
    private function __construct(){}
    static function getClassA(){
        $a = new A();
        return $a;
    }        
}

// 看到这里确实返回的是 A 的实例.但不是同一个对象.

$a1 = A::getClassA();
$a2 = A::getClassA();
echo "\$a1 的类是 ".get_class($a1)." , \$a2 是 ".get_class($a1);
if($a1 === $a2){ 
   echo "<br> \$a1 \$a2 指向同一对象.";
}else{ 
   echo "<br> \$a1 \$a2 不是一个对象.";
}

4.我们已经通过static方法返回了A的实例。但还有问题。我们如何保证我们

多次操作获得的是同一个实例的呢?解决办法:static的属性在内部也只有一个。

static 属性能有效的被静态方法调用。将这个属性也设置成private,以防止外部调用。

先将这个属性设置成 null。每次返回对象前,先判断这个属性是否为 null 。

如果为 null 就创建这个类的新实例,并赋值给这个 static 属性。如果不为空,

就返回这个指向实例的 static 属性。

class A{
    private static $a = null;
    private function __construct(){}
    static function getClassA(){
        if( null == self::$a){
            self::$a = new A();
        }       
        return self::$a;
    }        
}
// 看到这里确实返回的是 A 的实例.但不是同一个对象.
$a1 = A::getClassA();
$a2 = A::getClassA();
echo "\$a1 的类是 ".get_class($a1)." , \$a2 是 ".get_class($a1);
if($a1 === $a2){ 
   echo "<br> \$a1 \$a2 指向同一对象.";
}else{ 
   echo "<br> \$a1 \$a2 不是一个对象.";
}

最终这里无论是多少次都是同一个对象。

下面给一个例子

<?php
class Database {
    private $_db;
    static $_instance;
    final private function __construct($dbname,$user=‘root‘,$password=‘‘,$port=‘3306‘) {
        $conStr = "dbname=".$dbname." user=".$user." password=".$password." port=".$port;
        $this->_db = pg_connect($conStr);
    }
    private __clone() {};//不允许被克隆
    public static function getInstance($dbname,$user=‘root‘,$password=‘‘,$port=‘3306‘) {
        if( ! (self::$_instance instanceof self) ) {
            self::$_instance = new self($dbname,$user=‘root‘,$password=‘‘,$port=‘3306‘);
        }
        return self::$_instance;
    }
    public function query($sql) {
        return pg_query($this->_db, $sql);
    }
}
?>

代码从这开始

**/

class Person{
    const HIGH=‘170‘;
    private $name;
    private $age;
    private $sex;
    public $class;
    public function __construct($name,$age,$sex,$class){
        $this->name=$name;
        $this->age=$age;
        $this->sex=$sex;
        $this->class=$class;
        $this->run();
    }
    private function run(){
        echo $this->name."在跑步".$this->age;
    }
    public function say(){
        echo $this->name."在说话";
    }
    public function say1($name){
        echo $name."在说话";
    }
public function __set($field,$value){
if($field=="age"){
if($value>200){
// return "非法数据";
                $value="非法数据"; 
}
}
$this->$field=$value;
}
    public function __get($field){
        return $this->$field;
    }
    public function __isset($property_name){
        return isset($this->$property_name);
    }
    public function __unset($property_name){
        unset($this->$property_name);
    }
    public function __call($function_name,$arguments){
        echo "您所调用的方法".$function_name."参数<br/>";
        echo var_dump($arguments)."不存在";
    }
    public function __toString(){
        return $this->name."qwertyuiop";
    }
    public function __clone(){
        $this->class=‘2‘;
    }
    public function tellhigh(){
        echo "身高是".self::HIGH;
    }
}
$person = new Person("东方不败",210,‘不详‘,‘大学‘);
$person->say();
// $person->run();
$person->say1("nihao");
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$person->age=220;
echo $person->age;
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
echo isset($person->class) ? "存在":"不存在";
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
unset($person->age);
echo isset($person->class) ? "存在":"不存在";
echo isset($person->age) ? "存在":"不存在";
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$person->age=80;
echo isset($person->age) ? "存在":"不存在";
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$person->drink(123,"we");
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
echo $person;//输出对象的引用
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
//下面写一个自动加载函数
function __autoload($classname){
    include_once ucfirst($classname)."Controller.php";
}
$mx=new Phone(1999,‘4.5英寸‘,‘2200mah‘,‘魅族MX2‘,‘MX2‘);
$mx->tell();
echo Phone::FUNC;
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$person1=clone $person;
echo intval($person1===$person);
echo $person1->class;
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$person->tellhigh();
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
echo Person::HIGH;
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
abstract class Student{
    abstract function say();
    abstract function study();
    public function tell(){
        echo "这是个抽象类里面的普通方法";
    }
}
class LStudent extends Student{
    public function a(){
        echo "我是LStudent类中的a方法";
    }
    public function say(){
        echo "重写抽象类中的say方法";
    }
    function study(){
        echo "重写抽象类中的study方法";
    }
}
$LS=new LStudent();
$LS->a();
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
$LS->say();
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
interface PS{
    const NAME=‘串口‘;
    function start();
    function work();
}
interface PS1 extends PS{
    function stop();
}
abstract class PS2 implements PS{
    function start(){
        echo "抽象类实现部分方法这里是start方法";
    }
}
class PS3 implements PS1{
    function start(){
        echo "抽象类实现全部方法这里是start方法";
    }
    function work(){
        echo "抽象类实现全部方法这里是work方法";
    }
    function stop(){
        echo "抽象类实现全部方法这里是stop方法";
    }
}
$ps=new PS3();
$ps->start();
echo "<br/>---------------------我是华丽丽的分界线---------------------<br/>";
echo PS::NAME;
?>

PHP面向对象总结,布布扣,bubuko.com

时间: 2024-12-10 03:52:58

PHP面向对象总结的相关文章

python学习 面向对象封装

from collectoins import namedtuplePoint=namedtuple('point',['x','y'])t1=Point(1,2)print(t1.x)print(t1.y)没有方法的类属性不会发生变化    定义简单 不能改变面向对象封装私有属性!!!私有方法!!!用装饰器描述的几个方法@property !!!@classmethod!!@staticmethod! 封装:class Teacher:     def __init__(self,name,p

python—面向对象的封装

封装 私有属性 class Teacher: __identifier = 'Teacher' #私有静态属性 def __init__(self,name,pwd) self.name = name self.__pwd = pwd #私有属性 内部使用,外部不能使用 def pwd(self): print(self.__pwd) alex = Teacher('alex','3714') alex.pwd() class Teacher: __identifier = 'Teacher'

python学习_day26_面向对象之封装

1.私有属性 (1)动态属性 在python中用双下划线开头的方式将属性隐藏起来.类中所有双下划线开头的名称,如__x都会自动变形成:_类名__x的形式.这种自动变形的特点是: a.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果.b.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的.c.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:_子类名__x,而父类中变形成了:_父类名__x,即双下滑线开头的属性在继承给子类时,子类是无法覆

python面向对象知识点疏理

面向对象技术简介 类: 用来描述具有相同的属性和方法的对象的集合.它定义了该集合中每个对象所共有的属性和方法.对象是类的实例.class 类变量:类变量在整个实例化的对象中是公用的.类变量定义在类中且在函数体之外.类变量通常不作为实例变量使用. 数据成员:类变量或者实例变量用于处理类及其实例对象的相关的数据. 方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖,也称为方法的重写. 实例变量:定义在方法中的变量,只作用于当前实例的类. 继承:即一个派生类(de

php学习笔记 面向对象中[接口]与[多态性]的应用

代码如下: <?php /* 接口技术 * * 接口是一种特殊的抽象类,抽象类又是一种特殊的类 * * 接口和抽象类是一样的作用 * * 因为在PHP是单继承的,如果使用抽象类,子类实现抽象类就不能再去继承其他的类了 * * 如果既想实现一些规范,又想继承其他类.就要使用接口. * * 接口和抽象类的对比 * * 1.作用相同,都不能创建对象,都需要子类去实现 * * 2.接口的声明和抽象类不一样 * * 3.接口被实现方式不一样 * * 4.接口中的所有方法必须是抽象方法,只能声明抽象方法(不

php面向对象

面向对象 什么是面向对象? 面向对象编程(Object Oriented Programming, OOP, 面向对象程序设计)是一种计算机编程架构,OOP的一条基本原则是计算机程 序是由单个能够起到子程序作用的单元或对象组合而成,OOP达到了软件工程的三个目标:重用性.灵活性和扩展性.为了实现整体 运算,每个对象都能够接收信息.处理数据和向其它对象发送信息. 什么是面向对象编程呢? 把每个独立的功能模块抽象成类形成 对象,由多个对象组成这个系统,这些对象之间都能够接收信息.处理数据和向其它对象

面向对象注意事项

在面向对象中,有实例变量和类变量,实例变量为类对象的实例成员,而类变量不仅类可以直接调用,而且类的对象也可以调用.类对象可以对实例变量进行添加.修改.删除操作等... 下面就用个示例来做参考: #!/usr/bin/env python # -*- coding:utf-8 -*- class PersonInfo(object): commity_data = 123 def __init__(self,name,age): self.name = name self.age = age de

java面向对象:面向对象的思想和概述

1:面向对象思想 面向对象是基于面向过程的编程思想. 面向过程:强调的是每一个功能的步骤 面向对象:强调的是对象,然后由对象去调用功能 2:面向对象的思想特点 A:是一种更符合我们思想习惯的思想 B:可以将复杂的事情简单化 C:将我们从执行者变成了指挥者 开发,设计,特征 面向对象开发 就是不断的创建对象,使用对象,指挥对象做事情. 面向对象设计 其实就是在管理和维护对象之间的关系. 面向对象特征 封装(encapsulation) 继承(inheritance) 多态(polymorphism

6 面向对象之类和对象

1 面向对象和面向过程的区别 两者都是软件开发思想,先有面向过程,后有面向对象.在大型项目中,针对面向过程的不足推出了面向对象开发思想. 区别: 1)编程思路不同: 面向过程以实现功能的函数开发为主,而面向对象要首先抽象出类.属性及其方法,然后通过实例化类.执行方法来完成功能. 2)封装性:都具有封装性,但是面向过程是封装的是功能,而面向对象封装的是数据和功能. 3)面向对象具有继承性和多态性,而面向过程没有继承性和多态性,所以面向对象优势是明显. 2 类和对象 对象:客观存在的实体(一个具体的

简说面向过程与面向对象

昨天白天,因为在室外活动,无事可做,所以我思考了一天,在想怎么才能比较清晰的向人解释这两个概念.所以我对这两个概念的字面意思做了一下详细的解释.没想到,这可能真的会帮助我们非常简单的理解这两个概念. 面向:从字面上理解面向,就是我们的脸对着的地方,引申为我们能看到. 过程: 过程是事物从开始,到发展,到结束的整个经历 那么面向过程就是:我们能看到, 一个事物从 开始->发展->结束. 这对于我们写程序的人来说,可能会有感触,因为一开始我们写程序时.都是按照事件的发展.去安排计算机,一步一步的做