1、类的定义:

类的关键字定义使用class

1.定义一个空类

Class Person{};

2.定义一个有成员属性和操作的类

Class Person{

//成员属性

$name     =  '';

//操    作

protected function getActionName() {

return $this->name;

}

}

3.定义一个不能被继承的类,使用final关键字

Final class Person{

成员属性........

操    作........

}

4.注意:final关键字不能用来修饰成员属性 ,只能修饰类和方法(final方法后面介绍)

5.这里举一个带有final的class

定义一个final的类FinalClass,包含一个公共函数

final class FinalClass {

public function ffun() {

echo “本类为final类”;

}

}

定义一个类ChildFinalClass 并继承FinalClass 类

class ChildFinalClass extends FinalClass {

public function fchildfun() {

echo ‘本类继承final类FinalClass ’;

}

}

这样当执行以上命令的时候系统会提示

Fatal error: Class ChildFinalClass may not inherit from final class (FinalClass)

证明由final关键字定义的class是不可以被子类继承的

2、类中成员属性的定义

常见成员属性声明是由关以下键字
public,var,protected,private开头的,然后跟一个变量来组成的。还有一些成员属性包括,静态static,常量const.

Public: 表示全局的,类内部外部子类都可以访问

Var:     php 5 版本中会认为这个成员属性为public类型的属性

protected 表示受保护的,只有本类或子类或父类中可以访问

private
表示私有的,只有本类内部可以使用

Static:    1)静态的属性,

2)用static修饰的成员属性可以被同一个类的所有对象共享

3) 静态的数据是在类第一次被加载的时候就存在了内存中的数据段中(初始化静态段)

4)类中使用self::成员属性名

5)类外  类名::成员属性名

Const:   1)类中常量属性,在类中声明常量必须使用const

2)类中使用  self::成员属性名

3)类外使用  类名::成员属性名

注意:属性中的变量可以初始化,但是初始化的值必须是常数,这里的常数是指php脚本在编译阶段时就为常数,而不是在编译阶段之后在运行阶段运算出的常数。例如,不能包含任何运算符,不能是任何变量,不能是一个函数等。

iv. 成员属性的调用方式:

在类的成员方法里面,可以通过 $this->property(property是属性名字)这种方式来访问类的属性、 方法,但是要访问类的静态属性或者在静态方法里面却不能使用,而是使用 self::$property。 在类的非静态方法里面可以使用伪变量 $this,这个伪变量是调用该方法的实例化对象引用。

接下来用代码对上面的内容做一下解释:

class FinalClass {

//static $a = strTolower();   
//这种写法错误

//const  A = 1+2;              //这种写法错误

//public $name = 123+456;     
//这种写法错误

static $a = '$a';

const  A = 'A';

public $name = '凤姐';

protected $sex = '男+女';

private $age = 23;

}

class ChildFinalClass extends FinalClass{

public function fchildfun(){

echo 'ChildFinalClass类中ChildFinalClass::$a->'.ChildFinalClass::$a."<hr>";

Echo 'ChildFinalClass类中ChildFinalClass::A->'.ChildFinalClass::A."<hr>";

echo '大家好,我叫'.$this->name."<hr>";

echo '我是:'.$this->sex.'生<hr>';

echo '我今年:'.$this->age.'<hr>';

//由于age是私有的成员属性,所以在这里将不会被调用,将提示没有定义此属性在ChildFinalClass类中。

}

}

$obj = new ChildFinalClass();

$obj->fchildfun();

3.类中操作定义

成员方法和成员属性一样也包括public,protected,private,static,final,abstract并且作用域也是一样的,接下来举一些例子供大家参考和理解。

v. 静态的成员方法只能访问静态的成员属性和成员方法,并且类内部访问静态方法可以使用self::静态方法(),  类外部访问使用类名::静态方法()

//定义一个公共方法

public function publickfun(){}

/定义一个受保护的方法

protected function protectedfun(){}

//定义一个私用方法

private function privatefun(){}

//定义一个抽象方法

abstract public function render($data);

2.魔术方法

概述

在面向对象编程中,PHP提供了一系列的魔术方法,这些魔术方法为编程提供了很多便利。php中的魔术方法通常以__(两个下划线)开始,并且不需要显示的调用而是由某种特定的条件出发。这篇文章简单总结了PHP中提供的魔术方法。

开始之前

在总结PHP的魔术方法之前先来定义两个类,以便后边示例使用:

复制代码代码如下:
<?php
class Device {
    public $name;           
    public $battery;        
    public $data = array(); 
    public $connection;     
 
    protected function connect() {
        $this->connection = 'resource';
        echo $this->name . ' connected' . PHP_EOL;
    }
 
    protected function disconnect() {
        $this->connection = null;
        echo $this->name . ' disconnected' . PHP_EOL;
    }
}
 
class Battery {
    private $charge = 0;
 
    public function setCharge($charge) {
        $charge = (int)$charge;
        if($charge < 0) {
            $charge = 0;
        }
        elseif($charge > 100) {
            $charge = 100;
        }
        $this->charge = $charge;
    }
}
?>

Device类有四个成员属性和两个成员方法。Battery类有一个成员属性和一个成员方法。

构造函数和析构函数

构造函数和析构函数分别在对象创建和销毁时被调用。对象被“销毁”是指不存在任何对该对象的引用,比如引用该对象的变量被删除(unset)、重新赋值或脚本执行结束,都会调用析构函数。

__construct()

__construct()构造函数是目前为止最经常使用的函数。在创建对象时,可以在构造函数中做一些初始化工作。可以为构造函数定义任意多个参数,只要在实例化时传入对应个数的参数即可。构造函数中出现的任何异常都会阻止对象的创建。

复制代码代码如下:
class Device {
   public function  __construct(Battery $battery, $name) {
       $this->battery = $battery;
       $this->name = $name;
       $this->connect();
    }
}

上面的示例代码中,Device类的构造函数为成员属性赋值并且调用了connect()方法。

复制代码代码如下:
将构造函数声明为私有方法,可以防止在类外部创建对象,这在单利模式中经常使用。

__desctruct()

析构函数通常在对象被销毁时调用,析构函数不接收任何参数。经常在析构函数中执行一些清理工作,比如关闭数据库连接等。

属性重载(Property Overloading)

有一点需要注意的是:PHP中的”重载”与其他大多数语言的重载不是太一样,虽然都实现了相同的功能。
属性重载涉及到的两个魔术方法主要是用来处理属性访问,定义了当我们尝试访问一个不存在(或不可访问)的属性时会发生什么。

__get()

魔术方法__get()在我们尝试访问一个不存在的属性时会被调用。它接收一个参数,该参数表示访问属性的名字,并且将该属性的值返回。在上面的Device类里,有一个data属性,该属性就在这里就起了作用,如下面得代码:

复制代码代码如下:
class Device {
    public function  __get($name) {
         if(array_key_exists($name, $this->data)) {
            return $this->data[$name];
        }
        return null;
    }
}

该魔术方法最常用的地方就是通过创建一个“只读”的属性来扩展访问控制。在上面的Battery类中,有一个私有属性$charge,我们可以通过__get()魔术方法将该属性扩展为在类外部可读但不能修改。代码如下:

复制代码代码如下:
class Battery {
    private $charge = 0;
 
    public function  __get($name) {
        if(isset($this->$name)) {
            return $this->$name;
        }
        return null;
    }
}

__set()

__set()魔术方法在我们尝试修改一个不可访问的属性时会被调用,它接收两个参数,一个表示属性的名字,一个表示属性的值。示例代码如下:

复制代码代码如下:
class Device {
    public function  __set($name, $value) {
        // use the property name as the array key
        $this->data[$name] = $value;
    }
}

__isset()

__isset()魔术方法在对一个不可访问的属性调用isset()方法时会被调用,它接收一个参数,表示属性的名字。它应该返回一个布尔值,用来表示该属性是否存在。代码如下:

复制代码代码如下:
class Device {
    public function  __isset($name) {
        return array_key_exists($name, $this->data);
    }
}

__unset()

__unset()魔术方法在调用unset()函数销毁一个不能访问的属性时会被调用,它接收一个参数,表述属性的名字。

对象转换为字符串

有时候我们需要将对象以字符串的形式表现出来。如果我们直接打印一个对象,那么程序将会输出一个错误信息:PHP Catchable fatal error: Object of class Device could not be converted to string

__toString()

__toString()在我们将对象当作字符串一样使用时会被调用,它不接收任何参数。该方法允许我们定义对象的表现形式。代码如下:

复制代码代码如下:
class Device {
    public function  __toString() {
       $connected = (isset($this->connection)) ? 'connected' : 'disconnected';
       $count = count($this->data);
       return $this->name . ' is ' . $connected . ' with ' . $count . ' items in memory' . PHP_EOL;
    }
    ...
}

__set_state()(PHP 5.1)

静态魔术方法__set_state(),在我们使用var_export()函数输出对象时会调用该方法。var_export()函数用来将PHP变量转换为PHP代码,它接收一个包含对象属性值的关联数组作为参数。示例代码如下:

复制代码代码如下:
class Battery {
    //...
    public static function  __set_state(array $array) {
        $obj = new self();
        $obj->setCharge($array['charge']);
        return $obj;
    }
    //...
}

克隆对象

默认的,对象都是按引用传值的。因此,在将一个对象赋值给另一个变量时,只是创建了指向该对象的一个引用,并没有复制该对象。为了实现真正得复制一个对象,我们需要使用clone关键字。
这种“按引用传递”的策略同样适用于包含在对象内部的对象。即使我们克隆了一个对象,在对象内部的任何对象都不会被克隆,因此最终的结果是两个对象共享了同一个内部对象。示例代码如下:

复制代码代码如下:
$device = new Device(new Battery(), 'iMagic');
$device2 = clone $device;
 
$device->battery->setCharge(65);
echo $device2->battery->charge;
// 65

__clone()

__clone()魔术方法__clone()可以解决上面的问题。当对一个对象使用clone关键字时,该魔术方法会被调用。在这个魔术方法里,我们可以实现任何子对象的克隆,代码如下:

复制代码代码如下:
class Device {
    ...
    public function  __clone() {
        // copy our Battery object
        $this->battery = clone $this->battery;
    }
    ...
}

对象序列化

序列化是讲任意数据转换为字符串格式的过程。序列化通常用来将整个对象存入数据库或写入文件中。当反序列化存储的数据时,我们可以得到序列化之前的对象。但是,并不是所有得数据都可以被序列化,比如数据库连接。幸运的是,有一个魔术方法可以帮我们解决这个问题。

__sleep()

魔术方法__sleep()在对一个对象序列化时(调用serialize())会被调用。它不接收任何参数,而且应该返回一个包含所有应该被序列化的属性的数组。在该魔术方法中,也可以执行一些其他操作。
有一点要注意的是,不要再该函数中进行任何的析构操作,因为这可能会影响正在运行的对象。

示例代码如下:

复制代码代码如下:
class Device {
    public $name;           
    public $battery;       
    public $data = array();
    public $connection;    
    //...
    public function  __sleep() {
        return array('name', 'battery', 'data');
    }
    //...
}

__wakeup()

魔术方法__wakeup()在对存储的对象反序列化时会被调用。它不接收任何参数,也没有任何返回值。可以用它来处理在序列化时丢失的数据库连接或资源。代码如下:

复制代码代码如下:
class Device {
    //...
    public function  __wakeup() {
        // reconnect to the network
        $this->connect();
    }
    //...
}

方法重载

PHP还有两个与成员方法相关的魔术方法__call()和__callStatic(),这两个魔术方法类似于属性重载方法。

__call()

魔术方法__call()在调用不存在或不可访问的方法时会被调用。它接收两个参数,一个是调用的方法的名字,一个是包含函数参数的数组。我们可以使用这种方法调用子对象中得同名函数。

在这个例子中,要注意函数call_user_func_array(),这个函数允许我们动态调用一个命名的函数。

示例代码如下:

复制代码代码如下:
class Device {
    //...
    public function  __call($name, $arguments) {
        // make sure our child object has this method
        if(method_exists($this->connection, $name)) {
            // forward the call to our child object
            return call_user_func_array(array($this->connection, $name), $arguments);
        }
        return null;
    }
    //...
}

__callStatic()

魔术方法__callStatic()与__call()的功能一样,唯一不同的是,该方法在尝试访问一个不存在或不可访问的静态方法时会被调用。示例代码如下:

复制代码代码如下:
class Device {
    //...
    public static function  __callStatic($name, $arguments) {
        // make sure our class has this method
        if(method_exists('Connection', $name)) {
            // forward the static call to our class
            return call_user_func_array(array('Connection', $name), $arguments);
        }
        return null;
    }
    //...
}

将对象作为函数

有时候我们会需要将对象作为函数使用。将对象作为函数使用,就像我们使用其他普通的函数一样,可以传参。

__invoke()(PHP 5.3)

魔术方法__invoke()在尝试将对象作为函数使用时会被调用。在该方法中定义的任何参数,都将被作为函数的参数。示例代码如下:

复制代码代码如下:
class Device {
    //...
    public function __invoke($data) {
        echo $data;
    }
    //...
}
$device = new Device(new Battery(), 'iMagic');
$device('test');
// equiv to $device->__invoke('test')
// Outputs: test

其他:__autoload()

__autoload()方法并不是一个魔术方法,但是这个方法非常有用。但是,对着PHP版本的更新,该函数已经不建议使用,取而代之的是spl_auto_register()函数。

PHP如何定义类及其成员属性与操作的更多相关文章

  1. PHP中如何定义类及其成员属性与操作

    1.类的定义: i. 类的关键字定义使用class 1.定义一个空类 Class Person{}; 2.定义一个有成员属性和操作的类 Class Person{ 成员属性........ 操    ...

  2. c#利用反射Assembly 对类和成员属性进行操作

    protected static void test() { //获取程序集 Assembly assembly = System.Reflection.Assembly.GetExecutingAs ...

  3. [javaSE] 反射-获取类的成员属性和构造方法

    成员属性和构造方法皆为对象,通过Class对象的方法可以得到 package com.tsh.reflect; import java.lang.reflect.Constructor; import ...

  4. c#遍历并判断实体或类的成员属性

    c#的Attribute有些类似java中的annotation,可以方便地在类成员中做修饰/限制作用. Demo: class ss { public stat BsonDocument Itera ...

  5. C#学习笔记(八)——定义类的成员

    一.成员的定义 1.定义字段 class Myclass { public int MyInt; } 可以使用readonly关键字,表示这个字段只能在执行构造函数的过程中赋值,或者由初始化语句赋值. ...

  6. typescript装饰器定义 类装饰器 属性装饰器 装饰器工厂

    /* 装饰器:装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,属性或参数上,可以修改类的行为. 通俗的讲装饰器就是一个方法,可以注入到类.方法.属性参数上来扩展类.属性.方法.参数的功能. 常 ...

  7. python面向对象的特点,类定义等,私有属性、公有属性、成员属性

    引子:类的对象在内存中的表示def dog(name,dog_type): def bark(d): print(d,'wang wang wang ...') data = { 'name':nam ...

  8. OC基础--结构体 枚举做类成员属性

    结构体  枚举作类的成员属性: 定义一个学生类 性别 -- 枚举 生日 入学日期  毕业日期  --  结构体 代码示例: 声明文件 Student.h: #import <Foundation ...

  9. [.net 面向对象编程基础] (10) 类的成员(字段、属性、方法)

    [.net 面向对象编程基础] (10) 类的成员(字段.属性.方法) 前面定义的Person的类,里面的成员包括:字段.属性.方法.事件等,此外,前面说的嵌套类也是类的成员. a.类的成员为分:静态 ...

随机推荐

  1. upc组队赛1 流连人间的苏苏

    流连人间的苏苏 题目描述 苏苏在做红尘仙的任务时,发现坐落于风景秀丽.四季如春的昆明市的云南中医学院. 没过多久,苏苏就喜欢上了这个学校.以致于苏苏忘了回涂山的时间,现在她只剩下d天的时间待在云南中医 ...

  2. github帐户和仓库的创建

    sign up is registration and sign in is logging in for "in" is to enter an existing account ...

  3. 【做题】sgu189 Perl-like Substr——dark模拟

    注:这篇博客纯属为凑篇数而生. 题面较长,幸运的是,网上给出了相当不错的翻译. 需要支持的操作很简单,即对子串提取.赋值和输出,且对时间复杂度没有要求.换言之此题有成为块链毒瘤题的潜质.难点在于输入的 ...

  4. 【问题解决:时区】连接MySQL时错误The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one time zone

    问题描述: MySQL升级到8.0.11之后连接数据库报错: Your login attempt was not successful, try again. Reason: Could not g ...

  5. 【#和$】MyBatis中#和$的区别

    一.结论 #{}:占位符号,好处防止sql注入 ${}:sql拼接符号 二.具体分析 动态 SQL 是 mybatis 的强大特性之一,也是它优于其他 ORM 框架的一个重要原因.mybatis 在对 ...

  6. hihoCoder week8 状态压缩·一

    状态压缩  写了两个半小时  太菜了 题目链接 https://hihocoder.com/contest/hiho8/problem/1 #include <bits/stdc++.h> ...

  7. 题解——P1133 教主的花园DP

    直接设二维状态具有后效性,会爆零 然后需要加一维 然后70 看了题解之后发现没有考虑1和n的关系 考虑之后,四十 然后懵逼 突然发现自己的ans更新写错了,导致每次ans都是第一个取30的情况的解 然 ...

  8. NodeJS 获取网页源代码

    获取网页源代码 node 获取网页源代码 var http = require('http'); var url = "http://www.baidu.com/"; // 参数u ...

  9. Java 数据库篇

    一.简易封装JDBC工具类: package com.jackie.MyBatis.main; import java.sql.Connection; import java.sql.DriverMa ...

  10. progressBar显示百分比

    this.lab_AllFiles.Text = progressBarAllFile.Value * 100 / progressBarAllFile.Maximum + "%" ...