封装
使用修饰符修饰成员属性和成员方法,最大限度的隐藏对象的内部细节,保证对象的完整性和安全性
对象把变量和函数用大括号装在一起
即 对象 = {成员属性+成员方法} = {变量 + 函数}
强调的是一个整体性.
对象内部, 成员方法可以直接访问成员属性. 因此,方法之间传递数据非常方便.
public 公有的
类的成员属性和成员方法, 可以在类的 外部 读取和调用.
如果成员方法前没有任何修饰符, 则默认为 public
class Person
{
public $name;
public function setName($str)
{
// 直接给成员属性赋值
$this->name = $str;
}
public function getName()
{
// 直接访问成员属性
return $this->name;
}
}
private 私有的
类的成员属性和成员方法, 只能在类的 内部 读取和调用.
私有的成员属性在类的外部 不能直接访问
私有的成员方法在类的外部 不能直接调用
// 借钱给朋友
class Person
{
private $card; // 银行卡
private $password; // 密码
private $money; // 身上的现金
// 取钱
private function qu_qian()
{
$this-> money = 银行->atm($this->card, $thid->password);
}
// 借给别人钱
public function gei()
{
$this->qu_qian(); // 取钱是对象自己完成的, 不需要别人知道, 所以也是私有.
return $this->money;
}
}
protected 受保护的
类的成员属性和成员方法, 只能在本类和子类中的 内部 读取和调用.
受保护的成员属性在类的外部 不能直接访问
受保护的成员方法在类的外部 不能直接调用
class Person
{
protected $name;
protected $sex;
protected $age;
protected function getAge()
{
return $this->age;
}
public function setAge($n)
{
if ($n>=0 && $n<120) {
$this->age = $n;
} else {
echo '设置年龄不在合理范围内!';
}
}
}
魔术方法
__get 获取对象中的非公有或不存在的成员属性时, 触发该方法 接受一个参数 属性名
__set 设置对象中的非公有或不存在的成员属性值时, 触发该方法 接受两个参数 (属性名,属性值)
class Test
{
private $name = '景水';
private $sex = '男';
private $age = 18;
// $prop 为要获取的属性名称
public function __get($prop)
{
return $this->$prop;
}
// $prop 为要设置的属性名称, $value 为要设置的具体值
public function __set($prop, $value)
{
$this->$prop = $value;
}
}
$obj = new Test;
echo $obj->name; // 触发 __get()
$obj->sex = '女'; // 触发 __set()
/*
这两个方法代替了多个 getXXX 和 setXXX 方法
从使用类的角度, 不需要知道 getXXX 和 setXXX 方法,
只是把成员属性当做public来使用即可, __get 和 __set 会自然的,
透明的起到 保护对象的目的.
*/
__call() 调用对象中非公有或不存在的成员方法时, 触发该方法 接受两个参数 触发场景:
class Test
{
// 私有方法,不能在外部直接调用
private function add($a, $b)
{
return $a + $b;
}
// $method 为要调用的方法名, $params 为调用方法时的参数数组
public function __call($method, $params)
{
return $this->$method(...$params);
}
}
$obj = new Test;
echo $obj -> add(3, 4); // 触发 __call() 返回 7
/*
有一种场景,可以利用__call在 原方法执行前,执行后添加代码.
如:
public function __call($method, $params)
{
// 前置代码 $this->$method(...$params); // 后置代码
}
*/
其它魔术方法
__isset 判断对象的非公有或不存在的属性时, 触发该方法 接受一个参数 属性名
__unset 销毁对象的非公有或不存在的属性时, 触发该方法 接受一个参数 属性名
class Test
{
private $name = '景水';
private $sex = '男';
private $age = 18;
// 返回真实的结果 $prop 要判断的属性名
public function __isset($prop)
{
return isset($this->$prop);
}
// 实现销毁私有属性 $prop 要销毁的属性
public function __unset($prop)
{
unset($this->$prop);
}
}
$obj = new Test;
isset($obj->name); // 触发 __isset()
unset($obj->sex); // 触发 __unset()
__clone 当对象被克隆时,触发该方法
class Test
{
private $name = 'wangjs';
public function __clone()
{
$this -> name = '上神';
}
}
$obj1 = new Test;
$obj2 = clone $obj1; // 触发 __clone
__invoke 当对象被当做函数调用时, 触发该方法
class Test
{
public function __invoke()
{
echo '你把我当成函数调用啦!';
}
}
$obj = new Test;
$obj(); // 触发 __invoke(), 可以用参数
__toString 当在脚本中直接对对象进行字符串操作的时候 触发该方法
作用: 代替对象进行字符串的操作
<?php
class A
{
public $name;
public function say()
{
return 100;
}
public function __toString()
{
//在方法中必须要返回一个字符串类型的值
return '100';
}
}
$a = new A;
echo $a;
?>
继承
就是别人有 但是我没有 这个时候需要使用继承 把它所有的东西都拿过来
//基本格式
class A
{
public $name='王建双';
public function say()
{
echo '水清则无鱼';
}
}
// B类具有A类所有的成员. B类为子类, A类为父类
class B extends A
{
// 这里面什么都不写, 也已经有A中的成员属性和成员方法
// 添加 成员属性 和 成员方法
public $sex = '男';
public function listen()
{
echo '认真听讲,不睡觉!<br>';
}
}
$b = new B; // 访问从父类继承的成员
echo $b -> name,'<br>';
$b -> say(); // 访问父类独有的成员
echo $b -> sex,'<br>';
$b -> listen();
/*
注意:
1) B 中还可以 添加 新的成员属性和方法
2) B 中还可以 重写 已有的成员方法.
重写成员方法的时候, 参数个数要一致, 构造方法可以不一致
*/
父类中的 私有成员( private ) 在子类中无法访问.
父类中的 受保护的 ( protected ) 修饰成员, 使成员在子类中也可以访问.
本类 子类 类的外部
public Y Y Y
private Y N N
protected Y Y N
单继承
在php中只支持单继承
// 父类 --- 人
class Person
{
public $name;
public $sex;
public $age;
public function say(){}
}
// 学生类 继承 人类
class Student extends Person
{
public $num;
public function write(){}
}
// 教师类 继承 人类
class Teacher extends Person
{
public $money;
public function teach(){}
}
/*
单继承是一次只能继承一个类,不能连续继承多个类
*/
子类的重载
1.如果子类对父类的方法进行重写之后,实例化的对象在调用该方法的时候,会调用子类方法.
2.如果在子类的方法中想调用父类中的同名方法,这个需要使用 parent::方法名()
3.子类中重写成员方法的时候,要求参数个数和类型要一致,但是构造方法可以不一致
class A
{
public $name;
public function __construct($name)
{
$this->name = $name;
}
public function add($a, $b)
{
return $a + $b;
}
}
class B extends A
{
public $sex;
// 重写构造方法时,参数可以不一致
public function __construct($sex, $name)
{
parent::__construct($name);
$this -> sex = $sex;
}
// 重写父类方法时,还要求参数一致(个数,类型)
public function add($x, $y)
{
parent::add($x, $y);
}
}
$b = new B;
echo $b -> add(3, 4);
final 关键字
用来修饰类和成员方法, 用final修饰的类可以实例化对象但不能被继承 修饰的方法可以被调用但不能被重写
// 表示本类不能被继承
final class A
{
// 表示该方法不能被重写
final public function say()
{
echo '就算你叫破喉咙我也会继续写下去!';
}
}
trait 关键字
与 class 相似, 但是用 trait 定义的结构不能实例化对象
通过在类中使用use 关键字,声明要组合的Trait名称
trait A
{
public function say()
{
echo '说话的方法.....';
}
}
trait B
{
public function eat()
{
return '吃饭的方法.....';
}
}
class C
{
// 使用 trait A和B 做为本类的组装零件
use A,B;
public function talk()
{
return '一起出去走走呀....';
}
}
class D extends C
{
public function run()
{
return '已在运行起来了.....';
}
}