zoukankan      html  css  js  c++  java
  • 【辅导】Task12 使用类和对象 主要知识点(2)

    这次辅导主要是对类的多态性进行讲解。由于PHP是弱类型语言,所以导致在有些特征上有与Java等语言不同的地方,但总体上是差不多的。

    1、实现类多态的三种途径

    类的多态,就是用基类(父类)去管理派生类(子类),这些父类与派生类具有一致的行为,当父类对象指向子类对象的时候,具有的是子类的行为。

    可以通过以下三种方式实现类的多态:

    (1)重写父类方法

    (2)使用抽象类

    (3)实现接口

    2、重写父类方法

    从父类继承,你会得到父类的所有属性和方法,只不过受保护级别限制,public成员,你可以使用,别人也可以访问;protected成员,你自己和自己的子类可以访问,别人不能访问;private成员,你看不到,也使用不了(这一点有分歧,有人认为私有属性和方法不继承)。

    在子类中,重新定义一个与父类同名的方法,称为方法重写。

    方法重写时的注意事项:

    (1)方法名与参数个数必须相同。参数不一致,会有warning提示。这一点与Java稍有不同。

    (2)重写的方法的保护级别必须小于等于父类的方法。父类方法是public的,重写方法可以public、protected、private都可以;父类方法是protected,重写方法可以是protected和private。父类方法是private的,那子类可以定义一个新方法(这个方法正好与父类方法同名)。

    (3)如果类的方法被声明为final,那这个方法不能被重写。如果类被声明为final,那这个类不能被继承了。

    子类调用父类成员使用范围运算符:parent::成员名,前提是保护级别允许(public或protected)。

    3、这真的是多态吗?

     

    上面的foreach循环中,$shape是什么类型的变量? 在循环中加个调试语句试一下:

    var_dump($shape);

    会发现$shape变量分别是Point、Circle、Rectangle、Cylinder和Cube类型对象。主要是因为PHP是弱类型,它是通过赋值的数据推断类型的。

    这意味着,如果不使用继承来完成这些类,只要保证这些类都有同样的getArea()和getVolume()方法,也可以实现这个功能。Java这类强类型不行,因为每个变量要有明确的类型,所以只能通过基类去管理派生类。

    但你如何保证呢?从另一种形式说,通过继承和方法重写(即多态),你可以保证一组类具有相同的行为,从这一点说,这也是多态。

    4、instanceof运算符

    instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例。

    子类属于父类的实例,所以如果 $c是Circle类对象,$c instacneof Point的结果是true。

    instanceof也可以用来判断类对象是否实现了某个接口。

    6、抽象类

    抽象类用abstract定义。类中只要有一个方法是抽象方法,这个类就必须定义为抽象的。如果全是实体方法,这个类也可以定义为抽象类。

    抽象类只能由子类来继承,不能用来实例化对象。因为不能实例化,所以没有构造函数与析构函数。

    子类从抽象类继承,必须实现(重写)所有抽象方法。其它实体方法可以重写也可以不重写,没有重写就继承过来。

    子类实现了抽象方法就是实体方法了,它的子类可以继承过来,可以重写也可以不重写。

    使用抽象类,主要是因为有些方法不好定义具体的行为,就交给子类来定义的,同时也保证子类具有一致的行为。

    方法重写规则与前面一致。

    7、接口

    接口使用interface定义。同类一样,不定义访问属性,都是public。

    接口名称建议是i开头,如iCountable。

    接口中可以定义方法和常量,都必须是public的。

    接口中定义的所有方法都是空方法(只是说明没有实现)。

    接口中可以定义构造函数。(工厂模式时有用,与Java不同)

    一个类要实现接口,使用implements关键字。一个类只能从一个父类继承,但可以实现多个接口。

    实现接口的类,必须实现接口中所有方法(不然会有致命错误Fatal error),并且实现时,方法的定义形式要与接口中的定义一致(方法名与参数名称均要完全相同)。

    接口也可继承自一个或多个接口,使用extends关键字。

    PHP没有完全解决好接口中的名称冲突问题。如果一个类实现多个接口,这些接口中可以有同名的方法,但这些方法的定义必须签名相同。

    接口中可以定义常量。常量使用方法与类的常量相同,后面讲。

    8、类的静态成员

    类中可以定义静态字段和静态方法,使用static关键字。

    在类的内部,使用self关键字来引用,如:self::$count

    在类的外部,使用类名来引用,如:Student::getCount()

    9、理解浅复制

     

    将一个类的对象(已经用new 实例化)赋值给一个变量,得到的是这个对象的引用(两个变量指向同一个对象),不管有没有用&运算符。

    使用clone运算符,可以将对象复制一份给变量(可以说是2个对象了)。但是如果这个对象里面的有字段是其它类的对象(比如学生对象里面有课程字段,它是Course类的对象),这些字段克隆过去仍然是引用(浅复制)。除非你去定义__Clone魔术函数(自己决定这些字段如何复制过去)。

    10、类的常量

    可以把在类中始终保持不变的值定义为常量。在定义和使用常量的时候不需要使用 $ 符号。使用const关键字来定义(不是使用define函数)。

     

    在类的内部,使用self关键字来引用,如:self::constant

    在类的外部,使用类名来引用,如:MyClass::constant

    11、trait简介

    trait是PHP提供的一种代码复用的方法,他主要用于类的组合(接口也是组合的一种方式,但接口中只有抽象方法)。

    trait的定义与class一样,除了关键字是使用trait而不是class。

    trait不能用来实例化对象,只能在定义类时,通过use语句引用到类中。(个人感觉没什么用,仅仅是方便程序员复用代码)。

    可以这么理解,继承是纵向组合代码,trait是横向组合代码。

    12、类型约束:方法的参数可以指定类型

    看下面的例子:

     

    为函数ShowArea指定了参数必须为Point类型,那么,Point类的子类都可以作为参数传递给它,结果是:

     

    但Student类对象不能传递给它,会有错误:

     

     

    类类型、接口、数组、Callable(函数)可以作为类型约束,但标量类型(如int,string)不能作为类型约束(因为能自动进行类型转换)。

    类中的方法也支持类型约束。

    13、练习一下

    将我们在Java中学习的,使用抽象类和接口方式实现的多态性演示,在PHP中实现一下。

  • 相关阅读:
    Qt计算器开发(三):执行效果及项目总结
    [HNOI2019]校园旅行
    How to fix nuget Unrecognized license type MIT when pack
    How to fix nuget Unrecognized license type MIT when pack
    git 通过 SublimeMerge 处理冲突
    git 通过 SublimeMerge 处理冲突
    git 上传当前分支
    git 上传当前分支
    gif 格式
    gif 格式
  • 原文地址:https://www.cnblogs.com/whitewin/p/12658394.html
Copyright © 2011-2022 走看看