作为程序员一定要保持良好的睡眠,才能好编程

接口中可以定义变量吗 可以定义常量吗?

发布时间:2018-09-05

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


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


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


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


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



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


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


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



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

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



代码演示:


bIn.php

interface bIn{

    const table='interface 中的 bIn 表';

    public function add();
    public function del();
    public function edit();
    public function find();

}



c.php

include_once 'bIn.php';
class c implements bIn{

    const table='c 表';
    public $ff='';

    public function add()
    {
        echo 'c---add<br>';
        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.php

class V{

    const table='v 中的 V 表';

    const Header=[
        'name'=>'jim',
        'age'=>17,
        'city'=>'beijing'
    ];

}


testV.php

include "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.php

include "V.php";

class testV extends V{
    const table='testV 中的 V 表';

    const Header=[
        'name'=>'jim',
        'sex'=>'n'
    ];
}



echo testV::table;

print_r(testV::Header);

echo "<hr>";

$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.php

include "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 "<hr>";

$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