OOP
类和接口中的常量都不能被覆盖
子类覆盖父类的方法时,PHP不会调用父类中已被覆盖的方法。
当一个子类覆盖其父类中的方法时,PHP 不会调用父类中已被覆盖的方法。是否调用父类的方法取决于子类。这种机制也作用于构造函数和析构函数,重载以及魔术方法。
面向对象的三大特征
封装
继承
只能继承一个类,可以引入多个接口。
子类就会继承父类所有 public 和 protected 的方法,属性和常量。除非子类覆盖了父类的方法,被继承的方法都会保留其原有功能。
子类无法访问父类的私有方法
多态
类
应该包含方法和属性
属性
public private protected
static 属性的调用方式
调用本类中的属性
self::
变
量
名
∗
∗
‘
调
用
父
类
中
的
属
性
‘
∗
∗
p
a
r
e
n
t
:
:
变量名** `调用父类中的属性` **parent::
变量名∗∗‘调用父类中的属性‘∗∗parent::变量名
调用静态属性时,一定要记得加$符号
在类外部调用一个受保护的静态属性时,不能用 className::$变量名
继承父类之后,可以直接通过className::$变量名 调用父类中的public static 变量
class stu{
pubic static $name =“this is myName”;
}
class xm extends stu{
}
echo xm::$name;//输出this is myName
可以申明类的属性的类型,以及方法的返回类型
注意子类与父类的申明的类型匹配,父类没申明则自由发挥
读取不可以访问的属性的值时,__get(),__set()方法会被调用
匿名类
exp:
KaTeX parse error: Expected '}', got 'EOF' at end of input: …c function log(msg)
{
echo $msg;
}
});
匿名类可以extends implements use
exp
class SomeClass {}
interface SomeInterface {}
trait SomeTrait {}
var_dump(new class(10) extends SomeClass implements SomeInterface {
private $num;
public function __construct($num)
{
$this->num = $num;
}
use SomeTrait;
});
访问修饰符
public 调用方式
(new className)->定义的变量名
protected 调用方式
private 私有方式
抽象类
一个类中有一个抽象方法的话,那这个类必须是抽象类。
继承一个抽象类的时候,子类必须实现父类中定义的所有抽象方法
,并遵循常规的继承
签名兼容性原则
不能比父类中的访问修饰符等级高,比如父类时public 子类实现时,不能为protected或者private
范围解析操作符号 ::
自动加载类
spl_autoload_register(function ($className){
require_once $className.".php";
});
aotuloadTest.php
<?php
class autoloadTest{
//code
}
test.php
<?php
//当前文件没有引入autoloadTest.php
spl_autoload_register(function ($className){
require_once $className.".php";
})
//调用时不存在则自动加载。
$obj = new autoloadTest();
构造函数
__constract()
如果子类定义看__constract(),则不会自动调用父类的__constract();要调用父类的构造函数则需要使用 parent::__constract();
协变与逆变
interface
接口中定义的所有方法必须是public,这是接口的特性
一个接口可以继承多个接口,类引入接口时,要全部实现接口和继承的接口中的方法。
interface A
{
public function foo();
}
interface B
{
public function bar();
}
interface C extends A, B
{
public function baz();
}
trait(类似插件)
一个类可以use多个trait,本类中的同名方法覆盖trait中的同名方法
优先顺序是来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。
多个插件中有同样一个同名方法,如果没有解决会报Fatal Error
trait trainTest{
//
}
class className{
use trainTest;
}
--
class Base {
public function sayHello() {
echo 'Hello ';
}
}
trait SayWorld {
public function sayHello() {
parent::sayHello();//**调用父类(class::Base)的sayHello()方法**
echo 'World!';
}
}
class MyHelloWorld extends Base {
use SayWorld;
}
trait
--------------------------------------------------------------
trait 重名冲突解决
insteadof //代替
as //别名
比如trait a,trait b中有同名方法talk, a::talk insteadof b::talk
就解决了冲突。 同时 b::talk as btalk;可以继续调用b中的talk方法
- 在trait 中 use trait = 用魔法打败魔法
- trait 中可以定义抽象方法
- trait 的静态变量被不同的类使用时 是互不影响的
- trait 中定义一个属性后,类就不能定义相同的名称的属性。除非定义的访问修饰符和初始值是一致的。
重载
给魔术方法声明为static时会报错
- 必须声明为pulic
- public __set(string $name, mixed $value): void
- public __get(string $name): mixed
- public __isset(string $name): bool
- public __unset(string $name): void
- public __call(string $name, array $arguments): mixed
- public static __callStatic(string $name, array $arguments): mixed
- public __call()
在给不可访问(protected 或 private)或不存在的属性赋值时,__set()
会被调用。
读取不可访问(protected 或 private)或不存在的属性的值时,__get()
会被调用。
当对不可访问(protected 或 private)或不存在的属性调用 isset() 或 empty() 时,__isset()
会被调用。
当对不可访问(protected 或 private)或不存在的属性调用 unset() 时,__unset()
会被调用。
在对象中调用一个不可访问方法
时,__call()
会被调用。
在静态
上下文中调用一个不可访问方法
时,__callStatic()
会被调用。
对象遍历
foreach((new className) as k e y = > key=> key=>val){}//会输出public修饰的属性
final
被定义了final的类,子类不能覆盖,有与final类同名的,会报一个fatal error
8.1.0开始可以对 产量使用final关键字
后期静态绑定
url:https://www.php.net/manual/zh/language.oop5.late-static-bindings.php
使用 self:: 或者 CLASS 对当前类的静态引用,取决于定义当前方法所在的类
exp:
<?php 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(); ?>这里B::test(),调用的是A中的test类,因为self::或者__CLASS__对当前类的静态引用,取决于当前方法所在的类