0%

面向对象收集

《谁伴我闯荡》是中国香港摇滚乐队Beyond演唱的一首粤语歌曲,由刘卓辉作词,黄家驹作曲,Beyond编曲,收录在Beyond于1991年9月6日发行的粤语专辑《犹豫》中。该歌曲也是Beyond自传式电影《莫欺少年穷》的插曲之一,也是Beyond为数不多的专为电影创作作品。另外,本歌曲在港剧《笑看风云》中也被用做插曲。

一、三大特性

  1. 封装
  2. 继承:一个类继承另一个类,则称继承的类为子类,被继承的类为父类。
    • 实现:使用extends
    • 限制:public和protected属性和方法可以被继承,private不可以
    • 结果:继承后子类自动拥有了父类的属性和方法。
      • 子类也可以复写父类的方法,即方法的重写
      • 子类也可以写自己特有的属性和方法,目的是实现功能的扩展。
    • 优点
      • 提高了代码的复用性,继承后就拥有父类的属性和方法
      • 提高了代码的维护性,子类可以重写父类的属性和方法,也可以定义自己特有的方法和属性
      • 实现多态的前提,父类定义基础方法,不同子类重写此基础方法从而实现多态
    • 缺点
      • 降低代码的灵活性,只要继承就肯定拥有父类的所有属性和方法
      • 增强了耦合性
  3. 多态

二、五大原则

  1. 单一职责原则SRP(Single Responsibility Principle)
  2. 开放封闭原则OCP(Open-Close Principle)
  3. 里氏替换原则LSP(Liskov Substitution Principle)
  4. 依赖倒置原则DIP(Dependency Inversion Principle)
  5. 接口分离原则(Interface Segregation Principle)
  6. 迪米特法则(Law of Demeter)

三、依赖注入/控制反转

  1. 依赖倒置原则(DIP):一种软件架构设计的原则,程序中所有的依赖关系都应该终止于抽象类或者接口(抽象概念)。
  2. 控制反转IoC(Inversion of Control):一种反转流、依赖和接口的方式(DIP的具体实现方式)。
    • 控制反转(Inversion of Control,缩写为IoC)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,总结即为获得依赖对象的方式反转了。IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序,降低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称DI),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体,将其所依赖的对象的引用传递给它。
  3. 依赖注入DI(Dependency Injection):将依赖对象的创建和绑定转移到被依赖对象类的外部来实现,用来反转依赖,是IoC的一种实现方式。
  4. IoC容器:依赖注入的框架,用来映射依赖,管理对象创建和生存周期(DI框架)。
  5. DI实现方式
    • 构造函数注入
    • 属性注入
    • 接口注入
  6. 依赖注入

四、重写

  1. 当一个父类和子类有一个方法,参数和名字完全一致,那么子类方法会覆盖父类的方法。

    • 子类中方法的访问权限一定不能低于父类被覆盖方法的访问权限,也就是一定要高于或等于父类方法的访问权限。
    • 子类中的方法参数一定要和父类保持一致,否则会报错(构造函数除外)
  2. demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
class Person
{
public $name;
public $sex;
public $age;

public function __construct($name, $sex, $age)
{
$this->name = $name;
$this->sex = $sex;
$this->age = $age;
}

public function say()
{
echo "名字:" . $this->name . ",性别:" . $this->sex . ",年龄:" . $this->age;
}
}

class Student extends Person
{
public $school;

public function __construct($name, $sex, $age, $school)
{
parent::__construct($name, $sex, $age);
$this->school = $school;
}

// public function say($test),报错:PHP Strict Standards: Declaration of Student::say() should be compatible with Person::say()
public function say()
{
// parent::say(); // 或Person::say();
echo "姓名:" . $this->name .",就读学校:" . $this->school;
}
}

// $p = new Person('张三','男',11);
// $p->say();

$s = new Student('张三','男',11,'北大');
$s->say();

五、重载

  1. PHP所提供的重载(overloading)是指动态地创建类属性和方法,通过魔术方法(magic methods)来实现。

    • 魔术方法的参数都不能通过引用传递
  2. 当调用当前环境下未定义或不可见的类属性或方法时,重载方法会被调用。

    • 所有的重载方法都必须被声明为public
  3. PHP中的重载与其它绝大多数面向对象语言不同:传统的重载是用于提供多个同名的类方法,但各方法的参数类型和个数不同。

    • 函数重载指方法的名称相同而参数形式不同,且能够通过函数的参数个数或参数类型将这些同名的函数区分开来,调用不发生混淆。即当调用的时候,虽然方法名字相同,但根据参数的不同可以自动调用相应的函数
    • 重载是多态的一种实现
    • 函数重载指一个标识符被用作多个函数名,且能够通过函数的参数个数或参数类型将这些同名的函数区分开来,调用不发生混淆。即当调用的时候,虽然方法名字相同,但根据参数的不同可以自动调用相应的函数。
  4. 属性重载魔术方法

    • public __set(string $name, mixed $value):void,给不可访问属性赋值时,__set()会被调用。
    • public __get(string $name):mixed,读取不可访问属性的值时,__get() 会被调用。
    • public __isset(string $name):bool,对不可访问属性调用isset()或empty()时,__isset()会被调用。
    • public __unset(string $name):void,对不可访问属性调用 unset() 时,__unset() 会被调用。
      • 属性重载只能在对象中进行
      • 在静态方法中,这些魔术方法将不会被调用,所以这些方法都不能被声明为static。
      • 从PHP5.3.0起,将这些魔术方法定义为static会产生一个警告。
  5. 方法重载魔术方法

    • public __call(string $name, array $arguments):mixed,在对象中调用一个不可访问方法时,__call()会被调用。
    • public static __callStatic(string $name ,array $arguments):mixed,在静态上下文中调用一个不可访问方法时,__callStatic()会被调用。
  6. 实现重载

    • 基于魔术方法实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class Overload{

public function __call($name, $args)
{
if ($name == 'test') {
switch (count($args)) {
case 1:
call_user_func_array([$this,'test1'], $args);
break;
case 2:
call_user_func_array('self::test2', $args);
break;
default:
throw new Exception("Not Found Action");
break;
}
}
}

public static function __callStatic($name, $args)
{
echo 'function name:'.$name,PHP_EOL,'args list:'.join(',', $args);
}

private function test1($arg0)
{
echo __METHOD__,PHP_EOL;
}

private function test2($arg0, $arg1)
{
echo __METHOD__,PHP_EOL;
}
}

$obj = new Overload();
$obj->test(1);
$obj->test(1,2);
Overload::myFunc('magic static func');
  • 基于参数个数实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class Overload
{
public function test()
{
$num = func_num_args();
$arg = func_get_args();
switch ($num) {
case 1:
$this->testOne($arg[0]);
break;
case 2:
$this->testTwo($arg[0], $arg[1]);
break;
default:
throw new Exception("Not Found Action");
break;
}
}

private function testOne($arg0)
{
echo __METHOD__,PHP_EOL;
}

private function testTwo($arg0, $arg1)
{
echo __METHOD__,PHP_EOL;
}
}

$obj = new Overload();
$obj->test(1); //Overload::testOne
$obj->test(1,2); //Overload::testTwo

六、面向对象面向过程面向接口

  1. 面向过程的编程的基本构成便是“过程”,过程实现的方式就是“函数”,我们通过不同函数来实现不同的功能,并按照程序的执行顺序调用相应的函数,组成一个完整的可以运行的应用程序。我们可以通过把不同的功能在不同的函数中实现或者给函数传递不同的参数来实现不同的功能,这是面向过程中模块化设计的原理。
  2. 面向对象,是把数据及对数据的操作方法放在一起,作为一个相互依存的整体,即对象。对同类对象抽象出其共性,形成类;类中的大多数数据,只能用本类的方法进行处理。类通过一个简单的外部接口与外界发生关系,对象与对象之间通过消息进行通信;程序流程由用户在使用中决定。
  3. 接口就是这样一种东西,定义一种规格,以保持团队开发的一致性和规范性。