批改状态:合格
老师批语:将类分层管理是一个好办法
<?php// 使用trait将公共的show()提取出来trait tDemo{public function show(){printf('<pre>%s</pre>', print_r(get_class_vars(__CLASS__), true));//这个地方的class就是指这个class。get_class_vars就是获得这个class中所有的vars。// __CLASS__: 返回当前类的名称字符串// self: 返回的当前类的引用}}class User1{use tDemo;protected $name = '张三';protected $gender = '男';}(new User1)->show();echo '<hr>';class User2{use tDemo;protected $name = '小王';protected $gender = '女';}(new User2)->show();
<?phptrait tDemo{// public static $name = 'trait中的属性';public static function hello(){return 'trait中的方法' . __METHOD__;}}// 基类/父类/超类abstract class Dad{public static function hello(){return '基类中的方法' . __METHOD__;}}// 子类/扩展类class Son extends Dad{// 引入trait// use tDemo;// public static $name = '扩展类中的属性';// public static function hello()// {// return '扩展类中的方法' . __METHOD__;// }}echo Son::hello();
<?phptrait tDemo1{// 打印所有属性public function getProps(){printf('<pre>%s</pre>', print_r(get_class_vars(__CLASS__), true));}}trait tDemo2{// 打印所有方法public function getMethods(){printf('<pre>%s</pre>', print_r(get_class_methods(__CLASS__), true));}}// 使用tDemo3来组合tDemo1和tDemo2这二个traittrait tDemo3{use tDemo1, tDemo2;}class Work1{// 扩展这个类的功能// 添加二个公共方法// 1. 打印所有属性// 2. 打印所有方法use tDemo1, tDemo2;public $name = '西瓜';public $price = 2;public function getInfo(){return $this->name . ': ' . $this->price;}}echo (new Work1)->getInfo(), '<hr>';echo (new Work1)->getProps();echo (new Work1)->getMethods();class Work2{// 此时我只需要引入一个trait就可以use tDemo3;public $name = '西瓜';public $price = 2;public function getInfo(){return $this->name . ': ' . $this->price;}}echo (new Work2)->getInfo(), '<hr>';echo (new Work2)->getProps();echo (new Work2)->getMethods();
<?phptrait tDemo1{public function display(){return __METHOD__;}}trait tDemo2{public function display(){return __METHOD__;}}trait tDemo3{use tDemo1, tDemo2 {// 给tDemo2::display()起个别名: td2tDemo2::display as td2;// 调用tDemo1::display()替换掉tDemo2::display()tDemo1::display insteadOf tDemo2;}}// 工作类尽可能写得代码清晰,简洁class Work{use tDemo3;}echo (new Work)->display(), '<hr>';// 别名访问tDemo2::displayecho (new Work)->td2();
<?php// 接口interface iDemo{public static function index();}// traittrait tDemo{// 将接口中的抽象方法的实现过程放在trait中实现,并在工作类中调用public static function index(){return __METHOD__;}}// 实现类class Hello implements iDemo{use tDemo;}// 客户端echo Hello::index();
这个时候需要将self换成static(前者的意思应该是绝对绑定的self,后者static则有相对绑定的意思—— 后期静态绑定)
self::总是与当前声明该方法(create)的类绑定,并不能与调用类(User/Product)绑定
static::关键字,可以自动与当前方法的调用类进行绑定
part1
<?phpabstract class CreateInstance{}class User extends CreateInstance{// 创建当前类的实例public static function create() : self{return new self();}}class Product extends CreateInstance{// 创建当前类的实例public static function create() : self{return new self();}}// 生成User的实例$user = User::create();var_dump($user);// 生成Product的实例$product = Product::create();var_dump($product);
<?phpabstract class CreateInstance{// 创建当前类的实例public static function create() : self{// self::总是与当前声明该方法(create)的类绑定,并不能与调用类(User/Product)绑定// 声明类: CreateInstance(抽象类)// 调用类: User, Product// 因此用下面这个就不行,需要用后面的static部分。// return new self();// 解决: 将类的定义与类的调用完全分离// 使用static: 后期静态绑定// 前期: 声明// 后期: 调用// static::关键字,可以自动与当前方法的调用类进行绑定return new static();}}class User extends CreateInstance{}class Product extends CreateInstance{}// 生成User的实例// 当前调用create()方法的类是User,它不是抽象类$user = User::create();var_dump($user);// 生成Product的实例$product = Product::create();var_dump($product);// static: 之前用来声明静态成员, 现在还有可以与静态成员 的调用类进行绑定
<?php// 实战: 双色球开奖的背景知识// 抽象类 + 接口 + trait// 奖品$prizes = ['电脑', '手机', '平板', '耳机', '拖鞋', '口罩'];interface iCreateId{public static function generateId($min, $max);}trait createId{// 生成一个唯一ID: 抽象方法的实现public static function generateId($min, $max){return mt_rand($min, $max);}}// 开奖类class DrawPrize implements iCreateId{// 当前接口中的抽象方法,放在了trait中实现,并引入到当前的工作类中use createId;// 发奖品public static function award($prizes, $id){return $prizes[$id];}}// $id = DrawPrize::generateId(0, 5);// $prize = DrawPrize::award($prizes, $id);// printf('奖品是: <span style="color:red">%s</span>', $prize);
<?php$prizes = ['钢笔','圆珠笔','铅笔','橡皮','手表','手机','宇宙飞船'];interface iCreateID{public static function generateId($min,$max);//这里是一个抽象方法,然后后面在trait中来实现。//没有大括号实现的就是抽象方法。}trait createID{public static function generateID($min, $max){return mt_rand($min, $max);}}class DrawPrize implements iCreateID{use createID;public static function award($prizes, $id){return $prizes[$id];}}$id = DrawPrize::generateId(0, 6);$prize = DrawPrize::award($prizes, $id);printf('一共有七个个奖品:<br>钢笔-圆珠笔-铅笔-橡皮-手表-手机-宇宙飞船<br><br>您的运气还不错,本次中奖的奖品是:<br ><span style = "color:red">%s<span>', $prize);
<?php// 引入接口iCreateId, trait: createIdrequire 'demo6.php';//上一个抽奖就是demo6.php// 抽象类: 彩票abstract class Lottery implements iCreateId{// 在trait中实现接口中的抽象方法use createId;// 1. 生成中奖所需要的球的编号。红球、蓝球都用一个function。红球从33个中最终随机产生6个,篮球从16个中随机产生1个。protected static function createBalls($min, $max, $num){// ①. 按开奖规则生成指定步长与数量的球编号$allBalls = range($min, $max, 1);// ②. 根据取出的球的数量来区别当前是红球还是蓝球。// 数量为1时取篮球。因此就是随机取1个即可。if ($num === 1) return $allBalls[array_rand($allBalls)];// ③. 取红球return array_filter(array_rand($allBalls, $num), function ($key) use ($allBalls) {// array_rand()返回的索引键名中有可能包括0,以及已经取出的key,需要过滤掉。// $num为打算取出的数量。//return array_key_exists($key, $allBalls);// 添加 ($key > 0) 进行过滤return ($key > 0) && array_key_exists($key, $allBalls);}) ;}// 2. 生成一个双色球的中奖号// red: [1,33, 6], blue: [1,16, 1]abstract protected static function doubleColorBall(array $redRule, array $blueRule);// 3. 随机生成一组试机号abstract protected static function createRandBalls(array $redRule, array $blueRule, array $range);}// 实现类: 抽奖class DrawLottery extends Lottery{// 生成一个双色球的中奖号// red: [1,33, 6], blue: [1,16, 1]public static function doubleColorBall(array $redRule, array $blueRule){// 1. 生成红球的red: [1,33, 6]$redBalls = self::createBalls(...$redRule);sort($redBalls);// 2.生成蓝球 blue: [1, 16, 1]$blueBalls = self::createBalls(...$blueRule);// 3. 将红蓝球进行组合生成一组中奖号码array_push($redBalls, $blueBalls);return $redBalls;}// 随机生成一组试机号public static function createRandBalls(array $redRule, array $blueRule, array $range=[1, 10]){$count = self::generateId(...$range);//...是将$range中的1-10进行了拓展。因为generateId(demo6中有)后面应该是($min,$max)。...发挥的作用其实就是这样的。$randBalls = []; //用来接收收取出来的随机数字。for ($i = 0; $i < $count; $i++) {$randBalls[]=self::doubleColorBall($redRule, $blueRule);}//产生出随机数组。return $randBalls;}}$draw = DrawLottery::doubleColorBall([1,33,6], [1, 16, 1]);$randBalls = DrawLottery::createRandBalls([1,33,6], [1, 16, 1], [1,6]);?><!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>模拟双色球</title><style>.container1 {display: grid;grid-template-columns: repeat(7, 40px);gap: 10px;margin-top: 10px;}.container1 > .ball {width: 40px;height: 40px;color: white;font-weight: bold;text-shadow: 1px 1px 1px #555;border-radius: 50%;box-shadow: 3px 3px 3px #888;text-align: center;line-height: 40px;}.container1 > .ball:nth-of-type(-n+6) {background-color: red;}.container1 > .ball:last-of-type {background-color: deepskyblue;}</style></head><body><h2>模拟双色球开奖</h2><h3>今日开奖号码: <small style="color: green"><?=date('Y年m月d日', time())?></small></h3><div class="container1"><?php foreach ($draw as $item) : ?><span class="ball"><?=$item?></span><?php endforeach;?></div><hr><h3>今日试机号:</h3><!--将上面显示一组号码的代码再套一个外层循环就可以--><?php foreach ($randBalls as $draw): ?><div class="container1"><?php foreach ($draw as $item) : ?><span class="ball"><?=$item?></span><?php endforeach;?></div><?php endforeach;?></body></html>
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号