1、类与对象基本知识
<?php
namespace _0815;
/**
* 1.属性重载: __get(),__set()
* 2.方法重载:__call(name,$args),__callStatic(name,$args)
*/
//面向对象的三大特征:封装,重载,继承
class User
{
// private:私有,封装
// private int $age = 20;
//一般不会一个一个声明私有变量,可以直接声明一个数组
private array $data = [
'age' => 20,
];
//查询接口/属性拦截器/魔术方法/属性重载:可以拦截对私有属性的访问,然后转移到一个指定的方法去进行
public function getAge()
{
return $this->age;
}
//如何把访问属性的非法请求重定向到一个方法呢
public function __get($name)
{
if (array_key_exists($name, $this->data)) {
//$this后面的变量不写$
// return $this->data[$name];
$result = $this->data[$name];
} else {
// return "$name 属性不存在";
$result = "$name 属性不存在";
}
//对于有些编辑器,有多个return时,会有警告
return $result;
//三元
// return array_key_exists($name,$this->data)?$this->data[$name] : "$name 属性不存在";
}
//非法请求指对没有的方法进行请求时所执行的操作
//可以自动拦截对于方法的非法访问
public function __call($name, $args)
{
//第一个参数是方法名称
//第二个参数是以数组表示的参数列表
printf('方法名:%s<br>参数列表:<pre>%s</pre>', $name, print_r($args, true));
}
//拦截静态方法的非法请求
public static function __callStatic($name, $args)
{
//第一个参数是方法名称
//第二个参数是以数组表示的参数列表
printf('方法名:%s<br>参数列表:<pre>%s</pre>', $name, print_r($args, true));
}
}
$user = new User();
// echo $user->$age;会报错,不能访问私有属性
echo $user->getAge() . '<hr>';
echo $user->age . '<hr>';
echo $user->age1 . '<hr>';
//非静态方法,类实例来访问
$user->hello('朱老师', '506174602');
//静态方法,类访问
User::world(100,200);
//ThinkPHP,查询构造器,数据库操作
class Query
{
//当这个查询类实例化时,应该自动连接数据库
// public function __construct()
// {
// self::$connect()
// }
public function table($table)
{
return $this;
}
public function where($table)
{
return $this;
}
public function find()
{
}
}
//查询入口类
class Db
{
public static function __callStatic($name, $arguments)
{
// echo $arguments[0];
return call_user_func_array([new Query(),$name],$arguments);
}
}
Db::table('think_user');
// Db::table('think_user')->where('id',1)->find();
上述运行结果:
2、类的继承与扩展
<?php
namespace _0815;
/**
* 类的扩展/抽象/最终
* 1.可继承的成员:protected
* 2.extends:类成员的来源
* 3.parent:父类引用
*/
class Person
{
//属性
//public:公共成员,当前类,类外部都可见
public $email = 'a@qq.com';
//private:私有成员,仅限当前类,类外部不可见
private int $id = 10;
//protected:受保护的,用在当前类,以及他的子类中,外部不可见
protected string $name;
//public>protected>private
//类中,类外,子类,public
//类中,子类:protected
//类中:private
//方法
public function __construct($name)
{
$this->name = $name;
}
//自定义方法
protected function getInfo(): string
{
return $this->name;
}
}
//继承/扩展一个类
//一旦执行了extends,就相当于把父类除了private的代码全部复制到当前类中
class Stu extends Person
{
//只需要扩展父类中的"属性和方法"
//1.属性扩展
//之前的
//private string $name;
//扩展的
private string $lesson;
private int $score;
//2.方法扩展
//构造方法
public function __construct($name, $lesson, $score)
{
//parent:引用父类
parent::__construct($name);
$this->lesson = $lesson;
$this->score = $score;
}
//函数重写
public function getInfo(): string
{
return parent::getInfo() . '同学,(' . $this->lesson . '),成绩:' . $this->score . '<br>';
}
}
$stu = new Stu('小王', 'php', 90);
echo $stu->getInfo();
//2.禁用父类,仅允许通过它的子类来访问父类成员
//把当前类,声明为"抽象类":abstruct
abstract class Demo1
{
public string $name = 'admin';
// public function getInfo($name)
// {
// return 'Hello ,' . $name;
// }
//如果某个方法没有具体实现,应该声明成抽象方法
abstract public static function getInfo($name);
}
class Demo2 extends Demo1
{
//在子类中,必须将父类中的抽象方法实现
public static function getInfo($name)
{
return 'Hello ,' . $name;
}
}
echo Demo2::getInfo('朱老师');
//抽象类:强制要求必须继承才能使用
//最终类:禁止继承,直接用
final class Demo3
{
}
// class Demo4 extends Demo3
// {
// }
上述运行结果:
3、接口
<?php
namespace _0815;
//接口:升级版的抽象类
//接口一般首字母用i
interface iUser
{
//常量
const NATION = 'CHINA';
//方法:public
public function m1();
public function m2();
}
//工作类:实现了接口的类
class Demo1 implements iUser
{
//接口的抽象方法,必须在工作类中全部实现
//如果声明为抽象类,就不用全部实现了
public function m1()
{
}
public function m2()
{
}
}
//如果实现类仅实现了接口的一部分抽象方法,应该声明为抽象类
abstract class Demo2 implements iUser
{
public function m1()
{
}
}
//Java,PHP是单继承,C++是多继承
//PHP可以通过接口来实现多继承
interface A
{
}
interface B
{
}
interface C
{
}
//Test类,同时从三个接口中获取成员,间接实现"多继承"
class Test implements A,B,C
{
}
interface iDB
{
//insert
public static function insert(array $data);
//update
public static function updata(array $data,string $where);
//delete
public static function delete(string $where);
//select
public static function select(array $options);
}
abstract class aDb
{
//insert
public static function insert(array $data)
{}
//update
public static function updata(array $data,string $where)
{}
//delete
public static function delete(string $where)
{}
//select
public static function select(array $options)
{}
}
class Db extends aDb
{
}
4、命名空间基础
<?php
namespace one;
//命名空间解决了:全局成员的命名冲突,借鉴了同名文件可以存入不同的目录下面
class Demo1
{
public static string $name = 'admin';
}
//当存在命名空间时,全局成员应该使用完整的名称
//类名 = 空间名称\类名
//::class 获取类的完整名称
echo Demo1::class . '<hr>';
namespace two;
class Demo1
{
}
echo Demo1::class . '<hr>';
//跨空间访问
// echo one\Demo1::$name;
//实际访问的是:'two\one\Demo1'
//跨空间访问时,必须从根空间/全局空间开始查询: \
$arr = new Demo1;
echo \one\Demo1::$name;
5、命名空间的路径名称
<?php
namespace _0815;
//1.当前路径:非限定名称 Index
//2.相对路径:限定名称 two\Index
//3.绝对路径:完全限定名称 \one\two\Index
namespace one;
class Index
{
public static function show()
{
return __METHOD__;
}
}
echo Index::show() . '<hr>';
//如果我在one空间中,访问 one\two中的成员
echo \one\two\Index::show() . '<hr>';
//全局成员的前缀,默认就是当前的空间名
//因为本身就在one里面,所以\one可以不写
echo two\Index::show() . '<hr>';
//use默认使用完全限定名称的类名/绝对路径
echo \one\two\three\Index::show() . '<hr>';
use \one\two\three\Index as UserIndex;
//起了别名之后,下面就不必写这么长了
echo UserIndex::show() . '<hr>';
//如果当前空间中没有index类,可以进一步简化
//use one\two\three\Index as Index
//如果当前类别名称与原始类名相同,可以不写
//即use one\two\three\Index as Index 等价于 use one\two\three\Index
//如果当前空间中有Index类,就不能省去as
//insteadOf:trait中解决命名冲突
//trait:一个特殊的类
//空间可分层管理
namespace one\two;
class Index
{
public static function show()
{
return __METHOD__;
}
}
echo Index::show() . '<hr>';
//空间可分层管理
namespace one\two\three;
class Index
{
public static function show()
{
return __METHOD__;
}
}
echo Index::show() . '<hr>';
上述运行结果: