PHP - 面向对象
程序员文章站
2022-04-29 12:27:27
...
PHP -- 面向对象
PHP – 面向对象
PHP – 面向对象
Table of Contents
- 函数调用
- 有 __clone 和无 __clone
- 继承
- protected
- static
- final
- const
- 后期绑定, 又叫延迟绑定
- 单例模式 instanceof
- 魔术方法
- 重载 覆盖
- 魔术常量
- 抽象类和接口
- 命名空间
- 其他对象方法
- 自动加载
- TODO SPL 函数
函数调用
class test { public function f1() { echo 'you call me!'; } public function f2() { f1(); }}$t = new test();$t->f2(); // 报错// public function f2() { // 正确// self::f1();// }// public function f2() { // 正确// static::f1();// }
有 __clone 和无 __clone
一个值得注意的地方 __clone() cannot accept any arguments
- 直接赋值 (复制), 不会产生新的对象
class test { public function __construct() { echo 'ok'; } public function __destruct() { echo 'fail', '
'; }}$a = new test();$b = $a; // 指向同一个内存空间echo '
';// ok// -----// fail- clone 会生成一个新的对象, 但不会调用构造函数
class test { public function __construct() { echo 'ok'; } public function __destruct() { echo 'fail', '
'; }}$a = new test();$b = clone $a; // 指向不同的 内存空间echo '
';// ok// ---------------// fail// fail- __clone 调用析构函数
class test { public function __construct() { echo 'ok', '
'; } public function __destruct() { echo 'fail', '
'; } public function __clone() { return self::__construct(); }}$a = new test();$b = clone $a; // 指向不同的 内存空间echo '
';// ok// ok// -----// fail// fail继承
class A { function foo() { if (isset($this)) { echo 'this is defined (', get_class($this), ')', '
'; } else { echo 'this is not defined', '
'; } }}class B { function bar() { A::foo(); }}$a = new A(); // this 变成 A$a->foo();A::foo();// this is defined (A)// this is not defined$b = new B(); // this 变成 B$b->bar();B::bar();// this is defined (B)// this is not defined继承的时候权限只能越来越大, 不能变小
class A { protected $a = 'a'; protected function f() { echo $this->a, '
'; }}class B extends A{ private function f() { echo $this->a, '
'; }}$b = new B();$b->f(); // 报错protected
class A { protected $a = 'a'; public function f() { echo $this->a, '
'; }}class B extends A{ public function f() { echo $this->a, '
'; }}$b = new B(); // 可以继承 protected$b->f();static
static 变量
所有实例化的实例化的类共享的变量, 其中一个改变了, 其他的也跟着改变class stu { public static $fee; function f($fee) { self::$fee += $fee; }}
static 方法
不可以操作$this 变量
, 使用 static 方法的情景, 一般的原则是某个方法中不包含$this
变量calss stu { static function func1() { static::func2(); } static function func2() { ... }}
调用:
stu::func2();
,stu::func1();
final
使用 finnal 的场景:
- 出于安全的考虑, 某个类的方法不允许被修改
- 不希望被其他的类继承
final 不能修饰成员属性 (变量)
final 方法, 表示此方法不能被重写
class BaseClass { public function test() { echo "BaseClass::test() called\n"; } final public function moreTesting() { echo "BaseClass::moreTesting() called\n"; }}class ChildClass extends BaseClass { public function moreTesting() { echo "ChildClass::moreTesting() called\n"; }}// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
final 类, 表示此类不能被继续被
extends
final class BaseClass { public function test() { echo "BaseClass::test() called\n"; } // 这里无论你是否将方法声明为 final,都没有关系 final public function moreTesting() { echo "BaseClass::moreTesting() called\n"; }}class ChildClass extends BaseClass {}// 产生 Fatal error: Class ChildClass may not inherit from final class (BaseClass)
const
class MyClass { const constant = 'constant value' ; function showConstant () { echo self :: constant . "\n" ; }}echo $class :: constant . "\n" ; // 自 PHP 5.3.0 起
后期绑定, 又叫延迟绑定
延迟绑定的意思, self 的绑定是运行时候计算, 看下面
class Par { public static function whoami() { echo 'parent', '
'; } public static function say() { self::whoami(); } public static function say2() { static::whoami(); }}class Sun extends Par { public static function whoami() { echo 'sun', '
'; }}Sun::say(); // parent, 因为执行环境变成了 parentSun::say2(); // sun, 保持静态单例模式 instanceof
class mysql { public static $ins; private function __construct() { /* do something */ } private function __clone () {} // 禁止继承的类修改自身, 也可以使用 final public static function getIns() { if (!(self::$ins instanceof mysql)) { self::$ins = new self(); } return self::$ins; }}$a = mysql::getIns();$b = mysql::getIns();var_dump ($a === $b); // true
魔术方法
- __get
class test { public $hello = 'normal hello'; public function __get($args) { if ($args == 'hello') { echo 'from get: hello'; } else if ($args = 'other') { echo 'from get: other'; } }}$t = new test();echo $t->hello, '
'; // normal hello, 如果存在不会调用 魔术方法echo $t->other; // 不能调用, 调用魔术方法- __set
class test { public $hello = 'normal hello'; public function __set($k, $v) { echo 'you want to set me! ', $k, '
'; $this->$k = $v; }}$t = new test();$t->ttt = 222;echo $t->ttt; // 可以设置$t->hello = 'another hello';print_r($t);// you want to set me! ttt// 222// test Object// (// [hello] => another hello// [ttt] => 222// )- __isset
class test { public function __isset($v) { return false; ..... return true; }}
$t = new test();if (isset($t->value)) { echo 'isset';} else { echo 'noset';}
- __unset
调用的属性不存在, 就会调用此函数, 主要用于友好操作
- __call
无权调用的时候, 传递两个参数, (function_NAME, array function_ARGS)class test { public function func_empty() { echo 'nothing here'; } public function __call ($func, $args) { self::func_empty(); }}$t = new test();
class test { public function func_empty() { echo 'nothing here'; } public function __call ($func, $args) { print_r($args); self::func_empty(); }}$t = new test();$t->abc('abc', 'def');// Array ( [0] => abc [1] => def )
- __callStatic
public static function __callStatic ( $name , $arguments ) { ... }
重载 覆盖
覆盖: override 指的是子类覆盖父类的方法, 在 PHP 中, 如果
子类和父类的参数不一样会有警告
重载: redeclare 指的是同一个类中包含两个相同名字的方法,PHP 不支持
实现重载的方法
func_num_args() 返回数据的参数的个数$arr = func_get_args() 让参数以数组的形式返回func_get_arg(0) 返回第一个参数func_get_arg(1) 返回第二个参数
public function f() { $arr = func_get_args(); foreach($arr as $v) { .... }}
魔术常量
__LINE____FILE____DIR____FUNCTION____CLASS____METHOD__
抽象类和接口
abstract
abstract class Car { abstract function func1();}class Fastcar extends Car { public function func1() { ... }}
- 继承类必须实现抽象类的 所有 方法
- 抽象类可以有自己的属性
- 抽象类可以有自己的实现方法, 也叫具体方法, interface 没有
- 可以有 protected 方法, interface 不可以
interface
interface iUsb { public function f();}class phone implements iUsb { public function f() { .. }}
定义规范
当多个类, 之间平级的, 有相同的方法, 但是实现不同
类可以实现多个接口, 接口可以实现多个接口
class t1 implements i1, i2, i3 { }interface i1 extends i2, i2, i3 {}
- 继承类要实现 接口的全部方法
- interface 不能有 private 的方法
- interface 里面的属性只能是 常量
- interface 里面不能实现方法, 抽象类可以, (可以理解接口里面全都是抽象方法)
- interface 可以定义常量
class Monkey { public function climb() { ... }}interface iBirdable { public function fly();}interface iFishable { public function swim();}class NewMonkey extends Monkey implements iBirdable, iFishable { public function fly() { ... } public function swim() { ... }}
抽象类和接口的区别我不是
很熟悉
T_T, mark 个 todo 以后再来补充- 如果要创建一个模型, 这个模型将由一些紧密的对象采用, 就可以使用抽象类. 如果要创建由一些不相关对象采用的功能, 使用接口
- 如果必须从多个来源继承行为, 就使用接口. 接口可以实现多个, 不可以继承多个抽象类
- 如果所有的类会有共享一个公共的行为实现, 就使用抽象类, 并在其中的实现该行为, 在接口中无法实现具体方法
命名空间
如果文件 1 有
test
对象, 文件 2 也有test
对象
在文件 3require 'file1.php';require 'file2.php';
那么就会出现冲突
test1.php
namespace test\file1;class test { public $val = 'this is file 1';}
test2.php
namespace test\file2; # 也可以使用别的命名空间 ...\...\...\...class test { public $val = 'this is file 2';}
test.php
用于加载访问
require 'test1.php';require 'test2.php';$t1 = new test\file1\test();$t2 = new test\file2\test();echo $t1->val, '
'; // this is file1echo $t2->val, '
'; // this is file2use test\file1 as file1;use test\file2 as file2;$t3 = new file1\test();$t4 = new file2\test();echo $t3->val, '
'; // this is file1echo $t4->val, '
'; // this is file2其他对象方法
class_alias(class_name, new_classname)get_class (OBJ)$arr = get_declared_classes() # 返回已经定义了的类get_parent_class (OBJ)interface_exists (INTER) # 是否存在接口method_exists (OBJ, FUNC_NAME) # 是否存在某个方法
自动加载
function __autoload ( $class_name ) { require $class_name . '.php' ;}$obj = new MyClass1 (); // 自动会调用上面的哪个函数, 参数名是 MyClass1$obj2 = new MyClass2 (); // 自动会调用上面的哪个函数, 参数名是 MyClass2
为什么函数里面的 require class 的生活周期可以到外层, 原因像下面的,
__autoload 被执行之后, 就相当于把函数里面的代码展示出来function well() { function test() { echo 'inside ', '
'; }}well(); // 一定要先调用test(); // inside__autoload 的实现spl_autoload_register —— 注册给定的函数作为 __autoload 的实现
function func() { require '...';}spl_autoload_register(func);
TODO SPL 函数
相关文章
相关视频
专题推荐
-
独孤九贱-php全栈开发教程
全栈 170W+
主讲:Peter-Zhu 轻松幽默、简短易学,非常适合PHP学习入门
-
玉女心经-web前端开发教程
入门 80W+
主讲:灭绝师太 由浅入深、明快简洁,非常适合前端学习入门
-
天龙八部-实战开发教程
实战 120W+
主讲:西门大官人 思路清晰、严谨规范,适合有一定web编程基础学习
- 最新文章
- 热门排行
- __set
- clone 会生成一个新的对象, 但不会调用构造函数
网友评论
文明上网理性发言,请遵守 新闻评论服务协议
我要评论