Lesson12_多态

回顾

静态代码块 static{} 在类加载时执行一次 Class.forName(“xxx”);

普通代码块 每创建一个对象,都会执行一次,在构造方法之前执行。可以写所有构造方法共有的代码

构造方法 调用了哪一个,执行哪一个

单例模式 SingleTon private构造方法,内部new对象,提供公开的访问方法,static该方法,static该属性

​ 饿、懒

方法重载 同一个类中,相同的方法名,不同的参数列表。这种现象叫方法重载

package 打包,分门别类的管理各个.java文件,避免文件名冲突 全小写、域名倒置

​ javac -d . Person.java // 编译Person.java文件,将生成的目录保存在当前目录下,-d 指定生成目录的位置

​ java com.lesson15.demo.Person // 加载类到虚拟机中,需要写类的完全限定名

继承 已有类 --> 新类 private、static、构造方法不能被继承, 不能继承 != 不能访问

方法重写 子类不满意继承来的方法,想要改写它。改写可以,但必须保证方法签名一致。“协变”,“发扬光大”

super 只是个关键字,本质不是引用变量。 super. super() / super(xxx)

final 断子绝孙,最终。final 类,没有子类; final 方法,不能重写;

​ final 基本数据类型,不能改数据; final引用数据类型,不能改地址;

Object常用方法 Object是所有类的鼻祖,根类,父类,基类,超类。

equals(Object obj) 比较this和obj是否相同, 默认是 ==

toString() 把对象信息以字符串形式返回,默认是 完全限定名@十六进制的哈希值

父类如果没有写无参构造方法,子类所有的构造方法都会报错。

因为子类所有的构造方法的第一句,都隐式调用了父类的无参构造方法。如果没有,就会报错。

对于该错误,也可以手动调用父类中定义的构造方法。

类关系

  • 继承:is-a
  • 实现:like-a
  • 依赖:一个类作为另一个类的方法的参数。has-a
  • 关联:一个类作为另一个类的属性出现。has-a
    • 聚合:代码表现同上,语义上较上面更强烈
    • 组合:代码表现同上,语义上较上面更强烈
  • 注意:创建一个类的时候,类的属性一定是用来描述这个类的,没有这个属性,类就不成立

多态概念、举例

  • 封装隐藏了类的内部实现机制,可以在不影响使用的情况下改变类的内部结构,同时也保护了数据。对外界而已它的内部细节是隐藏的,暴露给外界的只是它的访问法。

  • 继承是为了重用父类代码。两个类若存在IS-A的关系就可以使用继承。同时继承也为实现多态做了铺垫。

  • 实例

    • 要求小明家里养宠物,他家里养了一直猫,现在要养一只狗,以后可能还会养其他动物。

      public class Cat{//吃东西public void eat() {System.out.println("猫吃鱼");}//发出叫声public void cut(){System.out.println("我是猫,喵喵叫")}//独有职责public void catch(){System.out.println("猫抓老鼠");}
      }
      public class Dog {//吃东西public void eat() {System.out.println("狗吃肉骨头");}//叫public void cut(){System.out.println("我是狗,汪汪叫");}//独有职责public void Janitor(){System.out.println("看家护院");}
      }
      public class Person {//喂猫public void feed(Cat cat){cat.eat();}//喂狗public void feed(Dog dog){dog.eat();}
      }
      
    • 以上代码看似没有问题,但是如果说,后期我这个人又想养其他宠物的话,就要改动person代码。同时也要创建一个新的类,而且又有重复的代码,比如eat这个方法。

    • 而多态就是解决这种问题。

  • 多:多个,不同;态:形态,效果,结果;

  • 相同的行为,作用在某一类不同的对象上,可能会有不同的解释,得到的效果不同。系统在编译期间并不确定具体执行的方法,而是在运行期才会确定。

行为     不同的对象    不同的效果
通电      电灯         亮电扇          转音响         响sayHi  中国人         你好美国人           Hello日本人            扣恩尼七哇韩国人        a ni a sei you按R        德玛          德玛西亚艾希          魔法水晶箭潘森         从天而降刷卡     超市          买脉动银行            取钱地铁            出行打人        小孩          苦女人         被抓老人            被碰瓷了做面食     面包机       面包面条机     面条超频        B系列主板       烧了Z系列主板     性能提升鼠疫病毒    小老鼠     没事儿人        生病开枪        手枪          哒,哒,哒步枪           哒哒哒,哒哒哒机枪            哒哒哒哒哒哒哒哒……
  • 上面的例子中,person这个类对于不同的宠物行为是相同的,都是feed这个行为。但是我们发现表现的结果不同,上面这种就是我们前面讲过的方法的重载。也可以认为是静态多态。但是这种方式没有太大的扩展性,如果要加一种宠物,必须要在person中重载一个方法。这就违反了开闭原则。

多态必要条件

  • 继承(extends) 或 实现(implements)
  • 方法重写
  • 父类型的引用持有其子类型的对象(*李氏替换原则),也就是编译时类型与运行时类型不同。对于我们想要的不同个表现,通过运行时动态的确定,而不是我们在代码上通过改代码来实现。
  • 注意:多态是方法的多态,不是属性的多态(多态与属性无关)。
  • 优点:使代码结构清晰。提高了项目的可扩展性。
  • 指允许不同类的对象对同一消息做出响应。即同一消息可以根据发送对象的不同而采用多种不同的行为方式。(发送消息就是函数调用)

上下转型

  • 上:父类型; 下:子类型

  • 向上转型

    • 父类型的引用 = 子类型的对象; *李氏替换原则 : 父类型的坑,子类对象都可以填。
    • 安全:因为子类 is-a 父类,所以向上转型总是安全的,不会报错。
    • 丢失:丢失子类特有的成员(鱼 --> 动物,就会丢失的能力;鸟 --> 动物,就会失去的能力)
  • 向下转型

    • 子类型的引用 = (子类型) 父类型的引用;

    • 恢复:重新拥有子类特有的成员(动物 --> 鱼,就可以继续游啊游;动物 --> 鸟,就可以继续飞啊飞),实现向下转型的前提是先向上转型。

    • 风险:因为父类型的引用可以持有各种子类的对象,所以不能轻易地转为某一种子类。需要instanceof

    • instanceof运算符

      instanceof是二元运算符,左边是对象,右边是类;当对象是右面类或子类所创建对象时,返回true;否则,返回false。比如:

      boolean res = animal instanceof Bird;
      // 判断animal引用持有的对象是否是Bird类型的,如果是,则res为true;否则,res为false;
      
    • getClass()的判定比instanceof运算符更严格(可以笼统的记忆为:getClass()是==,instanceof是<=)

动态绑定与静态绑定(PJ49图)

  • 绑定:指将方法的调用表达式与方法体的代码结合,这个过程就叫绑定。
  • 动、静:指的是方法,动、静的区别在于何时能确认调用的方法是哪一个

  • 静态绑定(早绑定)

    程序运行之前可以确定的,是静态绑定。静态绑定不存在多态。

    private 、static、final修饰的方法和构造方法,这四种方法都是静态绑定的。

  • 动态绑定(晚绑定)

    程序运行之后,对象创建后才可以确定调用的是哪个方法。多态是基于动态绑定的

  • 总结:对于面向对象而已,多态分为编译时多态和运行时多态。其中编辑时多态是静态的,主要是指方法的重载,它是根据参数列表的不同来区分不同的函数,通过编辑之后会变成两个不同的函数,在运行时谈不上多态。而运行时多态是动态的,它是通过动态绑定来实现的,也就是我们所说的多态性。

  • 多态:多态就是指程序中定义的引用变量所指向的具体类型和通过该引用变量发出的方法调用在编程时并不确定,而是在程序运行期间才确定,即一个引用变量倒底会指向哪个类的实例对象,该引用变量发出的方法调用到底是哪个类中实现的方法,必须在由程序运行期间才能决定。因为在程序运行时才确定具体的类,这样,不用修改源程序代码,就可以让引用变量绑定到各种不同的类实现上,从而导致该引用调用的具体方法随之改变,即不修改程序代码就可以改变程序运行时所绑定的具体代码,让程序可以选择多个运行状态,这就是多态性。
  • 对于Java而言,它多态的实现机制遵循一个原则:当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法。
  • 当超类对象引用变量引用子类对象时,被引用对象的类型而不是引用变量的类型决定了调用谁的成员方法,但是这个被调用的方法必须是在超类中定义过的,也就是说被子类覆盖的方法,但是它仍然要根据继承链中方法调用的优先级来确认方法,该优先级为:this.show(O)、super.show(O)、this.show((super)O)、super.show((super)O)。

提高之经典分析


public class A {public String show(D obj) {return ("A and D");}public String show(A obj) {return ("A and A");} }public class B extends A{public String show(B obj){return ("B and B");}public String show(A obj){return ("B and A");}
}public class C extends B{}public class D extends B{}public class Test {public static void main(String[] args) {A a1 = new A();A a2 = new B();B b = new B();C c = new C();D d = new D();System.out.println("1--" + a1.show(b));System.out.println("2--" + a1.show(c));System.out.println("3--" + a1.show(d));System.out.println("4--" + a2.show(b));System.out.println("5--" + a2.show(c));System.out.println("6--" + a2.show(d));System.out.println("7--" + b.show(b));System.out.println("8--" + b.show(c));System.out.println("9--" + b.show(d));     }
}

练习

  1. 打印中心,安装打印机,可以打印打印机作为打印中心的成员属性,打印学员信息,不同的打印机打印结果不同。
  2. 张三(Person)可以开关家里的任何电器,比如电灯、电视、电扇等(电器类)。使用继承和多态来实现开关(open close)电器(on off)的方法。
  3. 定义交通工具类,有公共汽车与小轿车。李四早上上班可以任意选择交通工具上班。
  4. 请完成射击类游戏:
    1. 有用户,用户登录时需要姓名,密码,登录成功后选择武器
    2. 武器的设计状态不同,如手枪射击时一发一发,步枪则可以连发
    3. 武器的选择最少有三种选择武器后确认开始,然后开枪射击。
    4. 射击时显示射击状态,造成伤害等。目标的血量都是100.
    5. 射击时打中与否通过设置特定比例,如手枪打中比例高,但伤害低。
    6. 目标死亡后显示胜利,选择是否继续游戏或退出。

Lesson12_多态相关推荐

  1. 重拳出击之《JVM》面试官版 (初哥勿看)

    <fonr color = black>JVM发展史,虚拟机发展史模块 java技术体系包括了几个组成部分? javaME.SE.EE分别是什么? 都说JDK7版本是第一个里程碑版本,为什 ...

  2. Python Day26:多态、封装、内置函数:__str__、__del__、反射(反省)、动态导入模块...

    ## 多态 ```python OOP中标准解释:多个不同类型对象,可以响应同一个方法,并产生不同结果,即为多态 多态好处:只要知道基类使用方法即可,不需要关心具体哪一个类的对象实现的,以不变应万变, ...

  3. Go 学习笔记(36)— 基于Go方法的面向对象(封装、继承、多态)

    Go 面向对象编程的三大特性:封装.继承和多态. 封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式 继承:使得子类具有父类的属性和方法或者重新定义.追加属性和方法等 多态:不同对象中同种行为的不 ...

  4. C#关于面对象多态例子

    //主的喂狗 class Program     {         static void Main(string[] args)         {             //我们来模拟一个主人 ...

  5. java为什么序列化不一致_java – 为什么Jackson多态序列化在列表中不起作用?

    杰克逊正在做一些真正奇怪的事情,我找不到任何解释.我正在进行多态序列化,当一个对象独立时它可以很好地工作.但是,如果将相同的对象放入列表并对列表进行序列化,则会删除类型信息. 它丢失类型信息的事实将导 ...

  6. 【C++】多态(早期绑定、后期绑定)、抽象类(纯虚函数)、虚析构函数

    我们都知道面向对象编程的三大特征是封装.继承.多态,今天我们就来说一下其中之一的多态. 概念: 多态: 多态字面意思就是多种形态,C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同 ...

  7. Go 分布式学习利器(13)-- Go语言的多态

    文章目录 1. 基本的多态实现 2. 空接口与断言 3. Go接口的最佳实践 1. 基本的多态实现 我们知道C++中实现多态是通过虚函数表 和 继承来 实现的. 类似如下代码: class Progr ...

  8. (1)访问控制 (2)final关键字 (3)对象创建的过程 (4)多态

    1.访问控制(笔试题) 1.1 常用的访问控制符 public - 公有的 protected - 保护的 啥也不写 - 默认的 private - 私有的 1.2 访问控制符的比较 访问控制符 访问 ...

  9. 多态---父指针指向子类对象(父类引用指向子类对象)

    我们都知道,面向对象程序设计中的类有三大特性:继承,封装,多态,这个也是介绍类的时候,必须提到的话题,那么今天就来看一下OC中类的三大特性: 一.封装 封装就是对类中的一些字段,方法进行保护,不被外界 ...

最新文章

  1. 多重继承和虚继承的内存布局
  2. Verilog: How to avoid 'Redeclaration of ansi port'
  3. Windows phone应从Android吸取四点教训
  4. 在博客园写了一年博客,收获的不仅仅是写作技能——我能一直保持积极的学习和工作态度...
  5. 全新章节抢先读 | 揭秘覆盖全端业务的文娱大前端技术
  6. Golang 连接Kafka
  7. python中的threading_python中threading超线程用法实例分析
  8. 如何强制 .NET 程序以 管理员模式 运行 ?
  9. 如何在WP-Config中设置WordPress错误日志
  10. SharePoint2013 备份还原
  11. 强大的独立日期选择器(date picker)插件 - Kalendae
  12. 贝叶斯线性回归方法的解释和优点
  13. 系统运行缓慢的问题定位步骤
  14. Deploy Office Communications Server 2007R2 Group Chat Server(一)
  15. 梦记录:1204(梦到观世音菩萨像)
  16. 麻省理工线性代数第二讲
  17. SQL 2008下载安装及问题解决
  18. idea mac 常用快捷键
  19. DOA估计谱峰搜索的一种策略
  20. HUAWEI nova 青春版“大尺度”内存,手机再满都不怕

热门文章

  1. python2和python3版本的区别
  2. 重庆大学考试计算机应用基础b卷,重庆大学2019年10月网上考试建筑结构设计B卷.docx...
  3. uniapp 打包安卓 Android 抖音app 前端篇~01
  4. 【Aegisub相关】VSCode插件:Aegisub Helper的安装、功能介绍及使用方法
  5. 《潜能成功学》----如何建立自信
  6. 如果把微信和支付宝比作钱包,那么数字人民币对应的是钱包中的内容
  7. Python for Data Analysis_2nd_Task 5 之 Pandas 进阶
  8. c#程序员面试题汇总,方便自己记录
  9. Wing FTP Server将文件复制到FTP服务器时发生错误,请检查是否有权限将文件放到该服务器上。解决方法
  10. 有未经处理的异常: 0xC0000005: 写入位置 0x00000014 时发生访问冲突