标签:
举例说明
abstract Class AbstractClass { abstract public function A();//这里不要携带body abstract protected function B();//这里不要携带body public 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/>"; } }
注意要点:
1)、如果AbstractClass中B为Public,则ClassA中B只能为public
2)、如果AbstractClass中B为Protected,则ClassA中B只能为public或Protected
3)、注意,AbstractClass的抽象方法不能为Private
实例:
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(){ } }
相同点
不同点
而 abstract class 的子类可以有选择地实现。这个选择有两点含义:
a) abstract class 中并非所有的方法都是抽象的,只有那些冠有 abstract 的方法才是抽象的,子类必须实现。那些没有 abstract 的方法,在 abstract class 中必须定义方法体;
b) abstract class 的子类在继承它时,对非抽象方法既可以直接继承,也可以覆盖;而对抽象方法,可以选择实现,也可以留给其子类来实现,但此类必须也声明为抽象类。既是抽象类,当然也不能实例化。
引用与推荐阅读>> PHP中的 抽象类(abstract class)和 接口(interface)
abstract关键字用于定义抽象方法与抽象类。
抽象方法指:没有方法体的方法,具体就是在方法声明的时候没有{},而是直接分号结束。一般用abstract定义的方法被称为抽象方法。在interface中所有的方法都是抽象方法。
定义抽象方法形如:
abstract function func_name();
抽象类指:只要一个类里面有一个方法是抽象方法,那么这个类就定义为抽象类。抽象类同样用abstract关键字来定义。关于抽象类的概念,更多了解可以看上面的解释。
final关键字,如果父类中的方法被声明为final,则子类无法覆盖该方法,如果一个类被声明为final,则不能被继承。
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.0 echo 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
推荐阅读>>
abstract class和interface有什么区别?
标签:
原文地址:http://www.cnblogs.com/ddddemo/p/5630137.html