面向对象(二)
多态
多种形态,多态分为两种,方法重写和方法重载,PHP不支持方法重载
方法重写
子类重写了父类的同名方法
规则:
- 子类中的方法必须和父类中的方法同名
- 子类可以拥有和父类不同数量的参数
- 子类中覆盖的方法不能比父类中被覆盖的方法更加严格
方法重载
通过参数的个数来区分不同的方法,PHP不支持。
面向对象的三大特性
-
封装,通过访问修饰符来实现封装
- Public
- Private
- protected
- 继承:子类继承了父类的属性和方法
-
多态:多种形态
- 方法重写
- 方法重载(PHP不支持)
私有属性的继承和重写
私有属性可以被继承,但是不能被重写
思考如下例题
方法修饰符
- static:静态的
- final:最终的
- abstract:抽象的
static修饰符
- static修饰属性叫静态属性,static修饰方法叫静态方法
- 静态属性在加载类的时候分配空间(普通属性在实例化的时候分配空间),所以不需要实例化就可以访问
-
因为静态成员属于类,不属于某个对象,所以通过类名来调用静态成员
- 类名::静态属性
- 类名::静态方法()
- 静态成员在内存中就一份。
多学一招: 由于普通方法在加载类的时候也加载了,所以也可以通过静态调用的方式来调用普通方法。
静态成员可以被继承
静态延时绑定
static也可以表示类名,表示调用当前访问的对象所属的类。
self:当前类的名字
self总是表示当前类的名字
final修饰符
final修饰的类不能被继承
final修饰的方法不能被重写
abstract修饰符
- abstract修饰的方法叫抽象方法,abstract修饰的类叫抽象类
- 只有方法的声明,没有方法的实现称为抽象方法。
- 一个类中只要只要有一个方法是抽象方法,这个类必须是抽象类
- 抽象类不可以被实例化,必须在子类中重新实现抽象方法
- 抽象方法的作用:用来定义命名规范的。
<?php
//类中只要有一个方法是抽象的,这个类就是抽象类
abstract class Goods {
protected $name; //商品名
public function setName($name) {
$this->name=$name;
}
public abstract function show(); //只有方法的声明,没有方法的实现
}
//手机类继承商品类
class Mobile extends Goods {
public function show() { //实现父类的抽象方法
echo $this->name,'<br>’;
}
}
//图书类继承商品类
class Book extends Goods {
public function show() { //实现父类的抽象方法
echo “《{$this->name}》<br>”;
}
}
//测试
header(‘Content-Type:text/html;charset=utf-8’);
$mobile=new Mobile();
$mobile->setName(‘iPhone7’);
$mobile->show();
$book=new Book();
$book->setName(‘PHP入门与精通’);
$book->show();
多学一招:类中一个抽象方法都没有也可以声明成抽象类。可以通过这种方法阻止类的实例化。
接口(interface)
- 如果一个类中所有的方法都是抽象方法,这个类就可以声明成接口。
- 使用interface关键字声明接口
- 接口中的抽象方法只能是public的,默认也是public。
- 接口不能继承,而是实现接口(implements)
- abstract和final不能修饰接口中的抽象方法
- 接口的作用也是用来定义命名规范
类不允许多重继承
一个父类可以有多个子类
一个子类不能有多个父类(只有c++可以多重继承,其他语言都不允许多重继承。)
多学一招:为什么很多语言不支持多重继承,因为多重继承容易产生二义性。
接口的多重实现
继承类同时实现接口
必须是先继承类再实现接口
类常量
常量也是加载代码的时候加载,所以也是通过类名来方法
类常量用const声明
const常量也可以放在接口中(接口中只能放抽象方法和常量)
参数约束
- 参数约束在PHP5.3以后才支持
- 只能约束对象,不能约束基本类型
父类可以指向子类的引用
父类可以保存子类对象的地址
<?php
class Person {
}
class Student extends Person {
}
class Employee extends Person {
}
function show(Person $obj) {
}
//测试
show(new Student);
show(new Employee);
分页功能
知识点:select * from 表名 limit 起始位置,记录数
起始位置从0开始。
分析:起始位置和页码的关系
一页放10条记录($pagesize=10)
页码($pageno) |
SQL语句 |
1 |
select * from contents limit 0,10 |
2 |
select * from contents limit 10,10 |
3 |
select * from contents limit 20,10 |
推导公式:$startno(起始位置)=($pageno-1)*$pagesize;
分析:总共有多少页
记录数($rowcount) |
页面总数($pagecount) |
30 |
3 |
31 |
4 |
1 |
1 |
推导公式:$pagecount=ceil($rowcount/$pagesize)
实现第一步:输出页码
点击页码——获取页码——通过页码获取页码的内容
代码实现
//第一步:获取总记录数
$sql=”select count(*) from contents where title=$titleid”;
$rs=mysql_query($sql);
$rows=mysql_fetch_row($rs);
$rowcount=$rows[0]; //获取到总记录数
//第二步:求得总页数
$pagesize=10; //页码大小
$pagecount=ceil($rowcount/$pagesize); //求得总页数
在页码底部循环输出页码
<tr>
<td colspan=’3′>
<?php for($i=1;$i<=$pagecount;$i++):?>
<?php if($pageno==$i):?>
<span class=”pageno”><?php echo $i?></span>
<?php else:?>
<a href=”?pageno=<?php echo $i?>&titleid=<?php echo $titleid?>”><?php echo $i?></a>
<?php endif;?>
<?php endfor;?>
<a href=”?pageno=1&titleid=<?php echo $titleid?>”>【首页】</a>
<a href=”?pageno=<?php echo $pageno-1?>&titleid=<?php echo $titleid?>”>【上一页】</a>
<a href=”?pageno=<?php echo $pageno+1?>&titleid=<?php echo $titleid?>”>【下一页】</a>
<a href=”?pageno=<?php echo $pagecount?>&titleid=<?php echo $titleid?>”>【末页】</a>
</td>
</tr>
实现第二步:获取页码,并取出当前页面中的内容
代码
//第三步:获取当前页的内容
$pageno=isset($_GET[‘pageno’])?$_GET[‘pageno’]:1; //获取当前页码
$pageno=$pageno<1?1:$pageno; //如果页码小于1,定位到第一页
$pageno=$pageno>$pagecount?$pagecount:$pageno; //页码大于总页数,定位到最后一页
$startno=($pageno-1)*$pagesize; //计算当前页的起始位置
$sql=”select * from contents where title=$titleid limit {$startno},{$pagesize}”;
$rs=mysql_query($sql);
完整代码
<!doctype html>
<html>
<head>
<meta charset=”utf-8″>
<title>无标题文档</title>
<style type=”text/css”>
table{
width:980px;
}
table,td,th{
border:solid 1px #000;
margin:auto;
font-size:14px;
}
.pageno{
font-size:24px;
color:#FF0000;
}
</style>
</head>
<body>
<?php
//连接数据库
mysql_connect(‘localhost’,’root’,’root’) or die(‘数据库连接失败’);
mysql_select_db(‘jokedb’);
mysql_query(‘set names utf8’);
?>
<!–显示分类–>
<?php
$rs=mysql_query(‘select * from title’);
?>
<table>
<tr>
<?php
$n=0;
while($rows=mysql_fetch_assoc($rs)):
?>
<td><a href=”?titleid=<?php echo $rows[‘Id’]?>”><?php echo $rows[‘Title’]?></a></td>
<?php
if(++$n%9==0)
echo ‘</tr><tr>’;
endwhile;
?>
</tr>
</table>
<!–显示内容–>
<?php
$titleid=isset($_GET[‘titleid’])?$_GET[‘titleid’]:1;
//第一步:获取总记录数
$sql=”select count(*) from contents where title=$titleid”;
$rs=mysql_query($sql);
$rows=mysql_fetch_row($rs);
$rowcount=$rows[0]; //获取到总记录数
//第二步:求得总页数
$pagesize=10; //页码大小
$pagecount=ceil($rowcount/$pagesize); //求得总页数
//第三步:获取当前页的内容
$pageno=isset($_GET[‘pageno’])?$_GET[‘pageno’]:1; //获取当前页码
$pageno=$pageno<1?1:$pageno; //如果页码小于1,定位到第一页
$pageno=$pageno>$pagecount?$pagecount:$pageno; //页码大于总页数,定位到最后一页
$startno=($pageno-1)*$pagesize; //计算当前页的起始位置
$sql=”select * from contents where title=$titleid limit {$startno},{$pagesize}”;
$rs=mysql_query($sql);
?>
<table>
<tr>
<th>编号</th> <th>内容</th> <th>作者</th>
</tr>
<?php while($rows=mysql_fetch_assoc($rs)):?>
<tr>
<td><?php echo $rows[‘Id’]?></td>
<td><?php echo $rows[‘Contents’]?></td>
<td><?php echo $rows[‘Author’]?></td>
</tr>
<?php endwhile;?>
<!–输出页码–>
<tr>
<td colspan=’3′>
<?php for($i=1;$i<=$pagecount;$i++):?>
<?php if($pageno==$i):?>
<span class=”pageno”><?php echo $i?></span>
<?php else:?>
<a href=”?pageno=<?php echo $i?>&titleid=<?php echo $titleid?>”><?php echo $i?></a>
<?php endif;?>
<?php endfor;?>
<a href=”?pageno=1&titleid=<?php echo $titleid?>”>【首页】</a>
<a href=”?pageno=<?php echo $pageno-1?>&titleid=<?php echo $titleid?>”>【上一页】</a>
<a href=”?pageno=<?php echo $pageno+1?>&titleid=<?php echo $titleid?>”>【下一页】</a>
<a href=”?pageno=<?php echo $pagecount?>&titleid=<?php echo $titleid?>”>【末页】</a>
</td>
</tr>
</table>
</body>
</html>