php 抽象类,接口,抽象方法,静态方法
1.Abstract class(抽象类)
- 抽象类是指在 class 前加了 abstract 关键字且存在抽象方法(在类方法 function 关键字前加了 abstract 关键字)的类。
- 抽象类不能被直接实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以通过继承抽象类并通过实现抽象类中的所有抽象方法,使抽象类具体化。
- 如果子类需要实例化,前提是它实现了抽象类中的所有抽象方法。如果子类没有全部实现抽象类中的所有抽象方法,那么该子类也是一个抽象类,必须在 class 前面加上 abstract 关键字,并且不能被实例化。
举例说明
abstract Class AbstractClass {abstract public function A();//这里不要携带bodyabstract protected function B();//这里不要携带bodypublic function C(){}//这里要携带body }class ClassA extends AbstractClass {public function A(){echo "Hello,I'm A <br/>";}protected function B(){echo "Hello,I'm B <br/>";}public function E(){echo "Hello,I'm E <br/>";} }
注意要点:
- 如果 AbstractClass实现了抽象方法 B() ,那么 ClassA 中 B() 方法的访问控制不能比 AbstractClass 中 B() 的访问控制更严格,也就是说:
1)、如果AbstractClass中B为Public,则ClassA中B只能为public
2)、如果AbstractClass中B为Protected,则ClassA中B只能为public或Protected
3)、注意,AbstractClass的抽象方法不能为Private
- 抽象方法与普通的方法不一样,它只是子类中普通方法的一个占位符(只是占个地主不启作用),没有任何代码,也没有"{}"包含,而是以";"结束的.
2.Interface(接口)
- 接口用关键字 interface 来声明。抽象类提供了具体实现的标准,而接口则是纯粹的模版。接口只定义功能,而不包含实现的内容。
- interface 是完全抽象的,只能声明方法,而且只能声明 public 的方法,不能声明 private 及 protected 的方法,不能定义方法体,也不能声明实例变量 。然而, interface 却可以声明常量变量 。但将常量变量放在 interface 中违背了其作为接口的作用而存在的宗旨,也混淆了 interface 与类的不同价值。如果的确需要,可以将其放在相应的 abstract class 或 Class 中。
- 任何实现接口的类都要实现接口中所定义的所有方法,否则该类必须声明为 abstract 。
- 一个类可以在声明中使用 implements 关键字来实现某个接口。这么做之后,实现接口的具体过程和继承一个仅包含抽象方法的抽象类是一样的。一个类可以同时继承一个父类和实现任意多个接口。 extends 子句应该在 implements 子句之前。 PHP 只支持继承自一个父类,因此 extends 关键字后只能跟一个类名。
- 接口不可以实现另一个接口,但可以继承多个
实例:
interface A {public function fA();Public function fB(); } interface B {public function fC();Public function fD(); } interface C extends A,B {} class M implements C {public function fA(){}public function fB(){}public function fC(){}public function fD(){} }
3.Abstract Class与Interface的异同
相同点
- 两者都是抽象类,都不能实例化。
- interface 实现类及 abstract class 的子类都必须要实现已经声明的抽象方法。
不同点
- interface 需要实现,要用 implements ,而 abstract class 需要继承,要用 extends 。
- 一个类可以实现多个 interface ,但一个类只能继承一个 abstract class 。
- interface 强调特定功能的实现,而 abstract class 强调所属关系。
- 尽管 interface 实现类及 abstract class 的子类都必须要实现相应的抽象方法,但实现的形式不同。 interface 中的每一个方法都是抽象方法,都只是声明的 (declaration, 没有方法体 ) ,实现类必须要实现。
而 abstract class 的子类可以有选择地实现。这个选择有两点含义:
a) abstract class 中并非所有的方法都是抽象的,只有那些冠有 abstract 的方法才是抽象的,子类必须实现。那些没有 abstract 的方法,在 abstract class 中必须定义方法体;
b) abstract class 的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。
- abstract class 是 interface 与 class 的中介。 abstract class 在 interface 及 class 中起到了承上启下的作用。一方面, abstract class 是抽象的,可以声明抽象方法,以规范子类必须实现的功能;另一方面,它又可以定义缺省的方法体,供子类直接使用或覆盖。另外,它还可以定义自己的实例变量,以供子类通过继承来使用。
- 接口中的抽象方法前不用也不能加 abstract 关键字,默认隐式就是抽象方法,也不能加 final 关键字来防止抽象方法的继承。而抽象类中抽象方法前则必须加上 abstract 表示显示声明为抽象方法。
- 接口中的抽象方法默认是 public 的,也只能是 public 的,不能用 private , protected 修饰符修饰。而抽象类中的抽象方法则可以用 public , protected 来修饰,但不能用 private 。
引用与推荐阅读>> PHP中的 抽象类(abstract class)和 接口(interface)
4.Abstract关键字
abstract关键字用于定义抽象方法与抽象类。
抽象方法指:没有方法体的方法,具体就是在方法声明的时候没有{},而是直接分号结束。一般用abstract定义的方法被称为抽象方法。在interface中所有的方法都是抽象方法。
定义抽象方法形如:
abstract function func_name();
抽象类指:只要一个类里面有一个方法是抽象方法,那么这个类就定义为抽象类。抽象类同样用abstract关键字来定义。关于抽象类的概念,更多了解可以看上面的解释。
5.Final关键字
final关键字,如果父类中的方法被声明为final,则子类无法覆盖该方法,如果一个类被声明为final,则不能被继承。
6.Static关键字
static关键字用来定义静态方法和属性,也可以用来定义静态变量以及后期静态绑定。
- 静态方法和属性:
声明类属性或方法为静态,就可以不实例化类而直接访问。静态属性不能通过一个类已实例化的对象来访问(但静态方法可以)。在没有指定访问控制(public,private,protected)的时候,属性和方法默认public。
静态方法不需要通过对象即可调用,所以伪变量$this在静态方法中不可用。
静态属性不可以由对象通过 -> 操作符来访问。
用静态方式调用一个非静态方法会导致一个 E_STRICT 级别的错误。
就像其它所有的 PHP 静态变量一样,静态属性只能被初始化为文字或常量,不能使用表达式。所以可以把静态属性初始化为整数或数组,但不能初始化为另一个变量或函数返回值,也不能指向一个对象。
自 PHP 5.3.0 起,可以用一个变量来动态调用类。但该变量的值不能为关键字 self,parent 或 static。
代码说明:
\Libs\Foo.php
<?php namespace Libs;class Foo {public static $my_static = 'foo';public function staticFunc(){return self::$my_static;} }
\Libs\SonFoo.php
<?php namespace Libs;class SonFoo extends Foo {public function sonStatic(){return parent::$my_static;} }
\Libs\UseFoo.php
<?php namespace Libs;class UseFoo {static public function index(){$eof = "<br/>";echo Foo::$my_static,1,$eof; //静态属性的调用方式$foo = new Foo();echo $foo->staticFunc(),2,$eof;echo $foo->my_static,3,$eof;//报错,因为不能使用->方式调用静态属性echo $foo::$my_static,4,$eof;$newfoo = 'Libs\Foo';echo $newfoo::$my_static,5,$eof;// As of PHP 5.3.0echo SonFoo::$my_static,6,$eof;$sonfoo = new SonFoo();echo $sonfoo->sonStatic(),7,$eof;} }
调用
UseFoo::index();
结果:
foo1
foo2
( ! ) Strict standards: Accessing static property Libs\Foo::$my_static as non static in ......Libs\UseFoo.php on line 15 | ||||
---|---|---|---|---|
Call Stack | ||||
# | Time | Memory | Function | Location |
1 | 0.0008 | 244064 | {main}( ) | ..\index.php:0 |
2 | 0.0026 | 262624 | Libs\UseFoo::index( ) | ..\index.php:51 |
( ! ) Notice: Undefined property: Libs\Foo::$my_static in ......Libs\UseFoo.php on line15 | ||||
---|---|---|---|---|
Call Stack | ||||
# | Time | Memory | Function | Location |
1 | 0.0008 | 244064 | {main}( ) | ..\index.php:0 |
2 | 0.0026 | 262624 | Libs\UseFoo::index( ) | ..\index.php:51 |
3
foo4
foo5
foo6
foo7
- 使用静态变量:
变量范围的另一个重要特性是静态变量(static variable)。静态变量仅在局部函数域中存在,但当程序执行离开此作用域时,其值并不丢失。看看下面的例子:
<?php function test($id) {static $count=0;echo "{$id}=>count is :".$count."<br/>";$count++; }test(1); test(2); test(3);
结果:
1=>count is :0 2=>count is :1 3=>count is :2
静态变量也提供了处理递归函数(递归函数是一种调用自己的函数)的方法。下面列出一个使用static变量完成递归的函数。
举个小例子
function test($end) {static $sum=0;if($end>0){$sum +=$end;$end--;test($end);}return $sum; } echo test(10);//输出55
注意注意注意!上面代码只是一个小例子,实际生产中千万不要这么来求和!!!
- 后期静态绑定:
自 PHP 5.3.0 起,PHP 增加了一个叫做后期静态绑定的功能,用于在继承范围内引用静态调用的类。
准确说,后期静态绑定工作原理是存储了在上一个“非转发调用”(non-forwarding call)的类名。当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分);当进行非静态方法调用时,即为该对象所属的类。所谓的“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()。可用 get_called_class() 函数来得到被调用的方法所在的类名,static:: 则指出了其范围。
该功能从语言内部角度考虑被命名为“后期静态绑定”。“后期绑定”的意思是说,static:: 不再被解析为定义当前方法所在的类,而是在实际运行时计算的。也可以称之为“静态绑定”,因为它可以用于(但不限于)静态方法的调用。
1).self:: 使用self::或者__CLASS__对之前类的静态引用,取决于定义当前方法所在的类
class A {public static function who() {echo __CLASS__;}public static function test() {self::who();} }class B extends A {public static function who() {echo __CLASS__;} }B::test();//输出A
2).static:: 后期静态绑定本想通过引入一个新的关键字表示运行时最初调用的类来绕过限制。简单地说,这个关键字能够让你在上述例子中调用 test() 时引用的类是 B 而不是 A。最终决定不引入新的关键字,而是使用已经预留的 static 关键字。
//简单用法class A {public static function who() {echo __CLASS__;}public static function test() {static::who(); // 后期静态绑定从这里开始} }class B extends A {public static function who() {echo __CLASS__;} }B::test();//输出B
在非静态环境下,所调用的类即为该对象实例所属的类,由于$this-> 会在同一作用范围内尝试调用私有方法,而static::则可能给出不同结果。static::只能用于静态属性
<?php class A {private function foo() {echo "success!\n";}public function test() {$this->foo();static::foo();} }class B extends A {/* foo() will be copied to B, hence its scope will still be A and* the call be successful */ }class C extends A {private function foo() {/* original method is replaced; the scope of the new one is C */} }$b = new B(); $b->test(); $c = new C(); $c->test(); //fails ?>
success! success! success!Fatal error: Call to private method C::foo() from context 'A' in /tmp/test.php on line 9
后期静态绑定的解析会一直到取得一个完全解析了的静态调用为止。另一方面,如果静态调用使用 parent:: 或者 self:: 将转发调用信息。
class A {public static function foo() {static::who();}public static function who() {echo __CLASS__."\n";} }class B extends A {public static function test() {A::foo();parent::foo();self::foo();}public static function who() {echo __CLASS__."\n";} } class C extends B {public static function who() {echo __CLASS__."\n";} }C::test();//输出结果为ACC
转载于:https://www.cnblogs.com/wazh/p/9528130.html
php 抽象类,接口,抽象方法,静态方法相关推荐
- python 抽象类、抽象方法、接口、依赖注入、SOLIP
python 抽象类.抽象方法.接口.依赖注入.SOLIP 1.程序设计原则:SOLIP SOLIP设计原则 1.单一责任原则(SRP) 一个对象对只应该为一个元素负责 2.开放封闭原则(OCP) 对 ...
- JavaSE面向对象:继承、多态、Super、Object类、重写、static、final、静态成员、懒汉式、饿汉式、单例设计模式、初始化块、抽象类、抽象方法、接口
感谢尚硅谷免费提供的视频 继承 ** 理解 ** 生活中的继承:子女继承了父母的财产或相貌或才华 java中的继承:一个类不用自己定义属性或方法,就已经具备了另一个类的属性和方法 把这种现象称为jav ...
- 百无聊赖之JavaEE从入门到放弃(十)抽象方法_抽象类 接口
目录 一.abstract 1.抽象方法 2.抽象类 3.抽象类的使用要点 4.示例代码 二.接口 1.接口是什么 2.接口的作用 3.区别 4.格式 (1)声明格式: (2)定义接口的详细说明 (3 ...
- 二十四、深入Java抽象类,抽象方法和接口
@Author:Runsen @Date:2020/5/31 作者介绍:Runsen目前大三下学期,专业化学工程与工艺,大学沉迷日语,Python, Java和一系列数据分析软件.导致翘课严重,专业排 ...
- 十一、接口(接口的概念,实现,继承,实现)、抽象类与抽象方法(抽象类,抽象方法概念,使用)...
接口 接口是一种用来定义程序的协议,它描述可属于任何类和结构的一组相关行为. 接口可由方法.属性.事件和索引器这四种成员类型的任何组合构成,但不能包含字段. 接口通过类继承来实现,一个类虽然只能继承一 ...
- php抽象类继承抽象类,PHP抽象类和抽象方法以及接口
PHP中的抽象类和抽象方法自己用的不多,但是经常会在项目中看到别人使用,同样,今天在看别人的代码的时候,发现使用了抽象类,就总结下: 抽象类: 1.如果一个类中有一个方法是抽象方法,则这个类就是抽象类 ...
- 接口(1):抽象类和抽象方法、接口
接口和内部类为我们提供了一种将接口与实现分离的更加结构化的方法. 这种机制在编程语言中并不通用.例如,C++对这些概念只有间接的支持.在java中存在语言关键字这个事实表明人们认为这些思想是很重要的, ...
- java中抽象类 接口_java中的抽象类与接口
1.抽象类的定义 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的,如果一个类中没有包含足够的信息来描绘一个具体的对象,这样的类就是抽象类. 2.简单实例 ...
- Java抽象类/接口
一.抽象类: 1.关键字:abstract ;修饰抽象类,抽象方法: 2.注释: 2.1.抽象类不可以创建对象,但是可以被声明引用(强制被使用多态): 2.2.抽象类不一定包含抽象方法,包含抽象方法一 ...
- java8接口写静态方法_Java 8接口更改–静态方法,默认方法
java8接口写静态方法 Java 8 interface changes include static methods and default methods in interfaces. Prio ...
最新文章
- 【二分答案】【最短路】bzoj1614 [Usaco2007 Jan]Telephone Lines架设电话线
- HOWTO:安装包卸载时如何保留部分文件不被卸载
- Java-Web JSP、Cookie和Session域对象
- ptmalloc内存分配释放
- kubeadm reset后安装遇到的错误:Unable to connect to the server: x509: certificate signed by unknown authority
- ionic 修改开发工具的配置
- 编写第一个Linux环境下程序的编译,下载记录
- 递归走迷宫java,java递归实现的迷宫游戏
- Hadoop Hive基础sql语法
- c语言英文单词倒着,C语言实现英文单词助手
- html不同类别的列表设置,HTML --列表
- css定位、position与float同时使用的情况
- 190331每日一句
- chrome等浏览器滚动全屏截图方法
- matlab图片测量尺寸_基于视觉的零件尺寸测量方法
- python模拟ios点击_弱弱的问下,ios的捷径可以实现模拟点击吗?
- GNSS模拟器助力控制器硬件在环仿真测试
- 元旦用SpringBoot撸了个博客网站送给大家
- 网络中的模块化和社区结构(Modularity and community structure in networks)
- pads单位切换的快捷键_PADS常用快捷键和一些技巧