抽象类
从具体事物抽出、概括出它们共同的方面、本质属性与关系等,而将个别的、非本质的方面、属性与关系舍弃,这种思维过程,称为抽象。
php中如果一个类的方法被定义为抽象,那么该类就是抽象类。抽象类不能被实例化。只能被子类继承,子类必须实现全部的抽象方法,并且访问修饰必须和父类相同或者更宽松。参数必须一致。
abstract class AbstractClass {
abstract public function test();
}
class Son extends AbstractClass{
public function test(){
echo "test";
}
}对象接口
接口泛指实体把自己提供给外界的一种[抽象化](可以为另一实体),用以由内部操作分离出外部沟通方法,使其能被内部修改而不影响外界其他实体与其交互的方式。
使用接口不需要实现哪些方法,只需要定义这些方法。具体的实现由类去实现。
接口通过interface定义。实现接口通过implements。接口可以被继承
接口中也可以定义常量。但是不能定义属性。接口允许多继承
interface Iter{
public function test();
}
class ClassT implements Iter{
public function test(){
}
}
interface Iter2 extends Iter {
public function test2();
}
class ClassT2 implements Iter2 {
public function test(){}
public function test2(){}
}
#多继承
interface Iter3 extends Iter1,Iter2{}
/**
* An example of duck typing in PHP
*/
interface CanFly {
public function fly();
}
interface CanSwim {
public function swim();
}
class Bird {
public function info() {
echo "I am a {$this->name}\n";
echo "I am an bird\n";
}
}
/**
* some implementations of birds
*/
class Dove extends Bird implements CanFly {
var $name = "Dove";
public function fly() {
echo "I fly\n";
}
}
class Penguin extends Bird implements CanSwim {
var $name = "Penguin";
public function swim() {
echo "I swim\n";
}
}
class Duck extends Bird implements CanFly, CanSwim {
var $name = "Duck";
public function fly() {
echo "I fly\n";
}
public function swim() {
echo "I swim\n";
}
}
/**
* a simple function to describe a bird
*/
function describe($bird) {
if ($bird instanceof Bird) {
$bird->info();
if ($bird instanceof CanFly) {
$bird->fly();
}
if ($bird instanceof CanSwim) {
$bird->swim();
}
} else {
die("This is not a bird. I cannot describe it.");
}
}
// describe these birds please
describe(new Penguin);
echo "---\n";
describe(new Dove);
echo "---\n";
describe(new Duck);Trait
Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制.无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合
trait定义
trait t{
public function test(){}
}
# 使用
class Test{
use t;
public function test2{
$this->test();
}
}优先级
从基类继承的成员会被 trait 插入的成员所覆盖。优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
class Base {
public function say(){
echo "base";
}
}
trait Test{
public function say(){
echo "trait";
}
}
class Son extends Base {
use Test;
public function test(){
$this->say();
}
}
$s = new Son();
$s->test();//trait
# 在子类中重写say。则调用子类的say方法
public function say(){
echo "son";
}多个trait组合
通过逗号分隔,在 use 声明列出多个 trait,可以都插入到一个类中
trait Hello {
public function sayHello() {
echo 'Hello ';
}
}
trait World {
public function sayWorld() {
echo 'World';
}
}
class MyHelloWorld {
use Hello, World;
public function sayExclamationMark() {
echo '!';
}
}冲突的解决
如果多个trait中。都有同名的方法,则会产生冲突,冲突会产生一个致命的错误。
为了解决多个 trait 在同一个类中的命名冲突,需要使用 insteadof 操作符来明确指定使用冲突方法中的哪一个
as 操作符可以 为某个方法引入别名
trait A {
public function smallTalk() {
echo 'a';
}
public function bigTalk() {
echo 'A';
}
}
trait B {
public function smallTalk() {
echo 'b';
}
public function bigTalk() {
echo 'B';
}
}
class Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
}
}
class Aliased_Talker {
use A, B {
B::smallTalk insteadof A;
A::bigTalk insteadof B;
B::bigTalk as talk;
}
}使用as修改访问控制
class Base {
public function say(){
echo "base";
}
}
trait Test{
public function say(){
echo "trait";
}
}
class Son extends Base {
use Test {say as private say2;}
public function say(){
echo "son";
}
}
$s = new Son();
$s->say2();//error使用多个trait组合
trait A{}
trait B{}
trait C{use A,B;}trait抽象成员方法
为了对使用的类施加强制要求,trait 支持抽象方法的使用
trait T{
abstract public function test();
}
class Test{
use T;
public function test(){}
}trait 静态方法
trait T{
public static function test() {};
}
class Test{
use T;
}
Test::test();trait定义属性
Trait 定义了一个属性后,类就不能定义同样名称的属性
trait PropertiesTrait {
public $same = true;
public $different = false;
}
class PropertiesExample {
use PropertiesTrait;
public $same = true; // PHP 7.0.0 后没问题,之前版本是 E_STRICT 提醒
public $different = true; // 致命错误匿名类
PHP 7 开始支持匿名类。 匿名类很有用,可以创建一次性的简单对象
匿名类被嵌套进普通 Class 后,不能访问这个外部类(Outer class)的 private(私有)、protected(受保护)方法或者属性。 为了访问外部类(Outer class)protected 属性或方法,匿名类可以 extend(扩展)此外部类。 为了使用外部类(Outer class)的 private 属性,必须通过构造器传进来.
$a = new class {
public function test(){
echo "test";
}
};
$a->test();