php中类静态成员描述不正确的是,静态成员与方法重载(对象成员访问限制,静态属性,静态方法,类常量,静态属性、静态方法的重载,案例连式操作)2019年3月4日22时...

今天,我们学习了静态成员与方法重载,具体内容由对象成员的访问限制,静态属性 方法的定义与访问,类常量与静态属性的区别与相同,静态属性方法的重载,还做了案例:仿Thinkphp的连式调用。

一、对象成员的访问限制

访问限定符规定了对象属性、方法的作用域,public在类内类外子类都可用,protected在类内 子类可用 ,private在类内可用,但是要在类外访问protected private的属性怎么办,通常是先用构造函数把各个属性初始化,然后在通过public的返回,外部就可以调用了。

实例

class Demo06

{

public $name;           //姓名

protected $position;    //职位

private $salary;        //工资

protected $department;  //部门

//构造函数

public function __construct($name, $position, $salary, $department)

{

$this->name = $name;

$this->position = $position;

$this->salary = $salary;

$this->department = $department;

}

//    获取职位的方法

public function getPosition(){

return $this->department === '培训部' ? $this->position : '无权查看';

}

//    获取工资的方法

public function getSalary(){

return $this->department ==='财务部' ? $this->salary : '无权查看';

}

public function setSalary($salary){

return $this->department ==='财务部' ? $this->salary = $salary : '无权更新';

}

}

$obj = new Demo06('明仔', '程序员', 9999, '培训部');

//$obj = new Demo06('明仔', '程序员', 9999, '财务部');

echo $obj->name.'
';

//echo $obj->position.'
';

//echo $obj->salary.'
';

echo $obj->getPosition().'
';

echo $obj->getSalary().'
';

$obj->setSalary(1111);

echo $obj->getSalary().'


';

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

class sub extends Demo06

{

}

$obj = new sub('豆豆', '职员', 8888, '财务部');

echo $obj->getSalary().'
';

echo $obj->getPosition();

运行实例 »

点击 "运行实例" 按钮查看在线实例

二、静态成员的定义与访问

类一般作为实例化对象的模版,但是存在以下的情况,可以不实例化成对象,直接用类来访问属性 方法,这就是静态属性、静态方法,统称为静态成员。

情况一、有时一个类只实例化成一个对象,那么为何不用类直接访问属性和方法?

情况二、有时同一个类实例化的许多对象,都有共同的属性需要调用,这样为何不给类一个统一属性,让他们共同调用,而不是实例化一次调用一次

具体访问是是不需要实例化  直接类::属性名  或者类::方法()

ps实例化的对象不能访问静态属性 但是可以访问静态的方法

实例

//类一般作为实例化对象的模版,访问类中的属性 方法都是先实例化成对象然后调用,但是可不可以通过类直接访问?

//静态属性 静态方法可以不实例化访问,静态成员的引入可以解决两个问题

//1就是有的时候只需要一个对象  那么实例化和直接用类是一样的

//2有的时候实例化成许多的对象,如果需要共享的属性,还的一个个赋值给属性  麻烦

class Demo01

{

public $product;

public static $price;

//    构造函数舒适化

public function __construct($product, $price)

{

$this->product = $product;

self::$price = $price;

}

//    对象方法

public function getInfo1(){

return $this->product.'价格是:  '.self::$price;

}

//    静态方法

public static function getInfo2($product){

return $product."价格是:   ".self::$price;

}

}

$obj = new Demo01('***', 5433);

echo $obj->product.'
';

echo Demo01::$price.'
';

echo $obj->getInfo1().'
';

echo Demo01::getInfo2($obj->product).'
';

//对象不能访问静态属性  但是可以访问静态方法

echo $obj->getInfo2($obj->product);

运行实例 »

点击 "运行实例" 按钮查看在线实例

三、类常量的定于与访问

类常量与静态属性基本一致,不同的是类常量的值不允许改变,静态属性可以被修改

实例

//类常量

class Demo02

{

//类常量同类属性一样,不需要实例化调用,而是直接由类调用

//区别是类常量不能改变,类属性可以改变

const NATION = '中国';

public static $sex = '男';

private $name;

public function __construct($name)

{

$this->name = $name;

}

public function getInfo()

{

//类常量和类属性一样在类内调用的话用self

return $this->name.'性别是: '.self::$sex.',国籍是:'.self::NATION.'
';

}

}

$obj = new Demo02('明仔');

echo $obj->getInfo();

//修改类属性

Demo02::$sex = '保密';

//修改类常量出错

//Demo02::NATION = 'riben';

echo $obj->getInfo();

运行实例 »

点击 "运行实例" 按钮查看在线实例

四、属性重载

但在类外访问protected  private属性是统称被限制,针对上述情况,由魔术方法来解决问题。

__get($name)  出现不能访问的情况,就自动调用此方法,然后将属性名作为参数穿进去,然后该方法在进行处理

__set($name, $value) 这方法是设置器

__isset($name) 这是判断是否由该属性

__unset($name)是销毁属性

实例

//属性重载

class Demo11

{

//设置私有属性

private $name;

private $salary;

protected $secret = '我有一个小秘密';

public function __construct($name, $salary)

{

$this->name = $name;

$this->salary = $salary;

}

//用__get 出现不能显示的类属性自动调用该方法作为获取器

public function __get($name)

{

//对用户进行判断 如果要查看secret 那么必须是admin的用户才能查看 否则无权查看

//  其他的类属性就可以直接查看

if ($name === 'secret') {

return $this->name === 'admin' ? $this->$name : '无权查看';

}

return $this->$name;

}

//__set 出现不能显示的类属性后 对该属性进行设置

public function __set($name, $value)

{

// 直接返回, 极少这样做

//        $this->$name = $value;

// 添加过滤机制

if ($name === 'salary') {

return $this->name === 'admin' ? $this->$name = $value : '无权修改';

}

return $this->$name = $value;

}

public function __isset($name)

{

if ($this->name === 'admin') {

if (isset($this->$name)) {

echo '属性存在';

} else{

echo '属性不存在';

}

} else{

echo '无权检测';

}

}

public function __unset($name)

{

if ($this->name === 'admin') {

unset($this->$name);

} else {

echo '无权删除';

}

}

}

$obj = new Demo11('明仔', 1111);

echo $obj->name.'
';

$obj = new Demo11('admin', 9999);

echo $obj->secret.'
';

$obj->salary = 8888;

echo $obj->salary;

echo "


";

isset($obj->salary);

echo '
';

unset($obj->salary);

isset($obj->salary);

运行实例 »

点击 "运行实例" 按钮查看在线实例

五、方法重载

针对在类外不能访问的方法由__call  今天方法__callStatic()

还有两个方法  call_user_func()  call_user_func_array()  他们将函数名作为参数,函数里的参数作为参数的两个方法,后者是吧参数用数组的形式穿进去

实例

//方法重载

class Demo12

{

//出现没有的类方法是自动调用__call  $name是方法名,$arguments 是所有参数

public function __call($name, $arguments)

{

return '方法名是  '. $name . '
 参数列表是' .'

'.print_r($arguments, true);

}

//也适用于静态方法

public static function __callStatic($name, $arguments)

{

return '方法名是  '. $name . '
 参数列表是' .'

'.print_r($arguments, true);

}

}

$obj = new Demo12();

echo $obj->getInfo('jj', 'kk', 123);

echo '


';

echo Demo12::getInfo11(10, 20, 30);

echo '


';

//  做个案例

//先了解两个函数

//call_user_func()  就是将一个函数作为参数  这个函数的参数做为他的参数 进行回调执行

//call_user_func_array()  和上面基本一致  只不过第二个参数是回调函数的参数组成的数组

function sum ($a, $b) {

return $a . '+' . $b .'='.($a+$b);

}

echo sum(10, 20);

echo '
';

//回调的方式为

echo call_user_func('sum', 10, 20);

echo '
';

echo call_user_func_array('sum', [10, 20]);

echo '
';

//那么把方法放在函数里 也可以调用

class Test1

{

public function sum ($a, $b) {

return $a . '+' . $b .'='.($a+$b);

}

}

$obj = new Test1();

echo call_user_func([$obj, 'sum'], 20, 40);

echo '
';

echo call_user_func([new Test1(), 'sum'], 20, 40);

echo '
';

//类的静态方法也适用

class Test2

{

public static function mul ($a, $b) {

return $a . '*' . $b .'='.($a*$b);

}

}

echo call_user_func('Test2::mul', 20, 40);

echo '
';

//也可以

echo call_user_func_array(['Test2', 'mul'], [20, 40]);

echo '
';

echo Test2::class;    //可以输出类的字符串

echo '
';

//也可以

echo call_user_func_array([Test2::class, 'mul'], [20, 40]);

运行实例 »

点击 "运行实例" 按钮查看在线实例

六、案例:连式调用

实例

//模拟ThinkPhp 连式操作 查询数据库

//引用外部类

require 'Query1.php';

class Db1

{

//数据库连接对象初始化

protected static $pdo = null;

//数据库连接方法 实现惰性连接 每次用时在连接  节省资源

public static function connection () {

self::$pdo = new PDO('mysql:dbname=php', 'root', 'root');

}

//  查询类的入口  通过用__callStatic  方法实现跨类调用

public static function __callStatic($name, $arguments)

{

//创建pdo对象连接数据库

self::connection();

//实例化查询类 将连接对象作为参数

$query = new Query1(self::$pdo);

return call_user_func_array([$query, $name], [$arguments[0]]);

}

}

$staffs = Db1::table('staff')

->field('id,name,position,mobile')

->where('id > 5')

->limit(5)

->select();

foreach ($staffs as $staff) {

echo '

'.print_r($staff, true);

}

运行实例 »

点击 "运行实例" 按钮查看在线实例

Query.php

实例

//模拟ThinkPhp 连式操作 查询数据库

//引用外部类

require 'Query1.php';

class Db1

{

//数据库连接对象初始化

protected static $pdo = null;

//数据库连接方法 实现惰性连接 每次用时在连接  节省资源

public static function connection () {

self::$pdo = new PDO('mysql:dbname=php', 'root', 'root');

}

//  查询类的入口  通过用__callStatic  方法实现跨类调用

public static function __callStatic($name, $arguments)

{

//创建pdo对象连接数据库

self::connection();

//实例化查询类 将连接对象作为参数

$query = new Query1(self::$pdo);

return call_user_func_array([$query, $name], [$arguments[0]]);

}

}

$staffs = Db1::table('staff')

->field('id,name,position,mobile')

->where('id > 5')

->limit(5)

->select();

foreach ($staffs as $staff) {

echo '

'.print_r($staff, true);

}

运行实例 »

点击 "运行实例" 按钮查看在线实例

总结

1、静态成员可以不用实例化不需要对象调用,有时比较简便

2、类常量是不能修改的

3、属性重载可以不用每个访问不到的属性单独设置获取的方法,只需要一个获取去 根据属性名来获取属性值

4、方法 重载同属性重载的意义一样,这里需要注意call_user_func call_user_func_array  这俩个回调函数的妙用,在后面的案例中,他作为跨类访问的入口,可以现在另外的类中定义好各种方法 然后根据情况在调用

5、连式调用的核心在与每个方法最后都返回$this 对象本身,这样才能让下一个方法由对象看调用  实现连式调用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值