接口、抽象类、实现类这三者有什么联系和区别?

接口:更高级的抽象类,不可以定义变量,可以定义常量

抽象类:介于实现类与接口之间的一个中间层 ,既可以定义变量、也可以定义常量

实现类:就是 implements  或 extends 接口或抽象类以后的类文件

结果:常量在接口中是不可以被复写的,接口中不允许定义变量。

那么说说我对接口中不能定义变量的理解,因为在接口中的所有方法都是抽象的,没有实现,没有办法去修改这个变量值的方法。

大家说,谁实现这个接口,谁去实现这个方法,不就可以了,其实上这么做,按照道理来说是可以的,但是语法是不支持这样做的,会报错。

其实如果完全就是要这样做,可以使用抽象类去完成这样的工作就可以了啊,即能完成变量的定义,也能定义变量。

通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。

对修改关闭,对扩展(不同的实现 implements)开放,接口是对开闭原则的一种体现。

代码演示:

bIn.phpinterface bIn{
const table='interface 中的 bIn 表';
public function add();
public function del();
public function edit();
public function find();
}
c.phpinclude_once 'bIn.php';
class c implements bIn{
const table='c 表';
public $ff='';
public function add()
{
echo 'c---add
';echo bIn::table;
// TODO: Implement add() method.
}
public function del()
{
// TODO: Implement del() method.
}
public function edit()
{
// TODO: Implement edit() method.
}
public function find()
{
// TODO: Implement find() method.
}
}
$c=new c();
$c->add();

现在通过浏览器去运行:

http://localhost/c.php

注意,我们复写了接口中的const 常量,那么运行会有什么样的提示:Fatal error: Cannot inherit previously-inherited or override constant table from interface bIn in E:\phpStudy\WWW\song\c.php on line 10

注意,常量在接口中是不可以被复写的,接口中不允许定义变量。如若定义,就是这样的提示

Fatal error: Interfaces may not include member variables in E:\phpStudy\WWW\song\bIn.php on line 13

换个场景:

V.phpclass V{
const table='v 中的 V 表';
const Header=[
'name'=>'jim',
'age'=>17,
'city'=>'beijing'
];
}
testV.phpinclude "V.php";
class testV extends V{
const table='testV 中的 V 表';
const Header=[
'name'=>'jim',
'sex'=>'n'
];
}
echo testV::table;
print_r(testV::Header);

运行结果:

testV 中的 V 表

Array ( [name] => jim [sex] => n )

结论:类与类之间的继承关系,是可以修改父类中const的。

但是还有一种结果:

V.php 添加一个send方法,方法主要内容是显示 header的内容class V{

const table='v 中的 V 表';
public $time='123';
const Header=[
'name'=>'jim',
'age'=>17,
'city'=>'beijing'
];
public function send(){
print_r(self::Header);
}
public function viewTime(){
print_r($this->time);
}
}
testV.phpinclude "V.php";
class testV extends V{
const table='testV 中的 V 表';
const Header=[
'name'=>'jim',
'sex'=>'n'
];
}
echo testV::table;
print_r(testV::Header);
echo "

";


$test=new testV();

$test->send();

得到结果:

testV 中的 V 表Array ( [name] => jim [sex] => n )

Array ( [name] => jim [age] => 17 [city] => beijing )

我们看到,打印出的结果还是 v.php中的数据。并没有打印出 jim 和  sex=n的数组。

我们再次改造一下:

testV.phpinclude "V.php";
class testV extends V{
const table='testV 中的 V 表';
const Header=[
'name'=>'jim',
'sex'=>'n'
];
public function send(){
print_r(self::Header);
}
}
echo testV::table;
print_r(testV::Header);
echo "

";


$test=new testV();

$test->send();

如果改成这样,就符合我们的预期了,可以正常显示出jim 和 n 了。

结论:在继承父类或抽象类,常量是可以被复写的。 继承抽象类,必须实现未实现的方法。

其实这里还有一点是错误的,这里做一下澄清,我们上边的代码中,使用静态变量都使用的是

self 这是初始化绑定,如果把父类修改成 static::Header 就能打印出在子类定义的常量。

下面是例子,我们看一下:

class V{
const table='v 中的 V 表';
public $time='123';
const Header=[
'name'=>'jim',
'age'=>17,
'city'=>'beijing'
];
public function send(){
print_r(self::Header);
}
public function viewTime(){
print_r($this->time);
}
}
class testV extends V{
const table='testV 中的 V 表';
const Header=[
'name'=>'jim',
'sex'=>'n'
];
}
$test=new testV();
$test->send();
//结果
//Array ( [name] => jim [age] => 17 [city] => beijing )
把V.php中的send方法中 self::Headler  改成  static::Headler<?php 
class V{
const table='v 中的 V 表';
public $time='123';
const Header=[
'name'=>'jim',
'age'=>17,
'city'=>'beijing'
];
public function send(){
print_r(static::Header);
}
public function viewTime(){
print_r($this->time);
}
}
class testV extends V{
const table='testV 中的 V 表';
const Header=[
'name'=>'jim',
'sex'=>'n'
];
}
$test=new testV();
$test->send();
//结果
//Array ( [name] => jim [sex] => n )
?>

看到变化了,现在使用的是子类中的Header 常量

static 是惰性加载

抽象类实例:

#Ab.php 这是一个抽象类
abstract class Ab{
const name='ab';
public $dec='';
public function edit(){
echo 'edit';
}
public abstract function add();
}
#testab.php 实现抽象方法
include_once 'Ab.php';
class testab extends Ab{
const name='bbbbb';
public function add()
{
// TODO: Implement add() method.
}
}
echo testab::name;

运行结果:bbbbb

很明显,已经被修改过了。但是必须去实现 未写完的抽象方法。

抽象类必须使用 abstract 关键字修饰抽象类

抽象方法必须使用 abstract 关键字修饰抽象方法

下面代码:

<?php 
/*
$data=[1,2,3,4,5,8];
foreach($data as &$v){
echo $v;
echo PHP_EOL;
}
foreach($data as $v){
echo $v;
}
echo PHP_EOL;
echo '------------------';
echo PHP_EOL;
$data=[1,2,3,4,5,8];
foreach($data as &$v){
$v=$v;
echo $v;
echo PHP_EOL;
}
foreach($data as $v){
echo $v;
}
echo PHP_EOL;
echo '------------------';
echo PHP_EOL;
$data=[1,2,3,4,5,8];
foreach($data as &$v){
$v=&$v;
echo $v;
echo PHP_EOL;
}
foreach($data as $v){
echo $v;
}
print_r($data);
echo PHP_EOL;
echo '---------666666666---------';
echo PHP_EOL;
$data=[0=>1,1=>2,2=>3,3=>4,6=>5,8];
foreach($data as &$v){
$v=&$v;
echo $v;
echo PHP_EOL;
}
foreach($data as $v){
echo $v;
}
print_r($data);
echo PHP_EOL;
echo '---------8888888888888888---------';
*/
/*
echo PHP_EOL;
class ParentModel{
static $a=33;
}
class SunModel extends ParentModel{
public function __construct($num){
self::$a=55;
}
public function getuser1(){
return self::$a;
}
public function getuser2(){
return $this->getuser1();
}
}
echo ParentModel::$a.PHP_EOL;
$sun=new SunModel(1);
echo $sun->getuser1().PHP_EOL;
echo $sun->getuser2().PHP_EOL;
*/
//https://www.jb51.net/article/136794.htm
class ParentModel{
static $a=33;
public function getuser3(){
return self::$a;
}
}
class SunModel extends ParentModel{
public function __construct(){
self::$a=55;
}
public function getuser1(){
return static::$a;
}
public function getuser2(){
return $this->getuser1();
}
}
echo ParentModel::$a.PHP_EOL;
$patternModel=new ParentModel();
echo $patternModel->getuser3().PHP_EOL;
$sun=new SunModel();
echo $sun->getuser1().PHP_EOL;
echo $sun->getuser2().PHP_EOL;
abstract class Ab{
const name='ab';
public $dec='';
public function edit(){
echo 'edit';
}
public abstract function add();
}
class testab extends Ab{
const name='bbbbb';
public function add()
{
// TODO: Implement add() method.
}
}
echo testab::name;

https://www.jb51.net/article/136794.htm