• Java中多态的优势和劣势是什么?


    什么是多态?

    在编程语言和类型论中,多态(英语:polymorphism)指为不同数据类型的实体提供统一的接口。 多态类型(英语:polymorphic type)可以将自身所支持的操作套用到其它类型的值上。

    面向对象的三大特征:封装性、继承性、多态性,多态性就是多态,多态是在封装的升华,可以说没有封装就么有多态。

    extends继承或者implements实现,无论是类与类之间的继承、类与接口之间的实现还是接口与接口间的继承,反正总会出现上下的层次关系,这种关系的产生就是多态性出现的前提。

    为了更好的明白什么是多态,来个小demo吧!

    多态demo

    场景:有学生、老师、超级管理员,难道每一个都要重复写吗,这个岂不是很繁琐,维护起来很困难,若干年后当做diamagnetic重构的时候可能你都不想看你的代码了吧,应该是真的很繁琐,很复杂。

    下面我们将创建三个子类【Student、Teacher、Administrator】和一个父类【Person】以及一个测试函数。

    父类,包含普通的变量和一个show方法。

    Person.java

    1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo1;
    2. public class Person {
    3. private String name;
    4. private int age;
    5. public Person() {
    6. }
    7. public Person(String name, int age) {
    8. this.name = name;
    9. this.age = age;
    10. }
    11. public String getName() {
    12. return name;
    13. }
    14. public void setName(String name) {
    15. this.name = name;
    16. }
    17. public int getAge() {
    18. return age;
    19. }
    20. public void setAge(int age) {
    21. this.age = age;
    22. }
    23. public void show(){
    24. System.out.println(name+","+age+"展示");
    25. }
    26. }

    学生类,继承父类属性和方法并重写父类show方法

    Student.java

    1. class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo1;
    2. public class Student extends Person{
    3. @Override
    4. public void show() {
    5. System.out.println("学生的信息"+getName()+","+getAge());
    6. }
    7. }

    老师类,继承父类属性和方法并重写父类show方法

    Teacher.java

    1. class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo1;
    2. public class Teacher extends Person{
    3. @Override
    4. public void show() {
    5. System.out.println("老师的信息"+getName()+","+getAge());
    6. }
    7. }

    超级管理员类,继承父类属性和方法并重写父类show方法

    Administrtors.java

    1. class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo1;
    2. public class Administrtors extends Person{
    3. @Override
    4. public void show() {
    5. System.out.println("管理员的信息"+getName()+","+getAge());
    6. }
    7. }

    为了不需要重写我们只需要new出想要的对象然后传入即可。这样就算后面需要添加更多类型的用户也只需要new出对象,控制传入register的参数即可。注意因为main函数是static的,所以下面的register也必须是static类型的。

    Test.java

    1. class="prettyprint hljs cpp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo1;
    2. public class Test{
    3. public static void main(String[] args) {
    4. Student student=new Student();
    5. student.setName("张三");
    6. student.setAge(20);
    7. Teacher teacher=new Teacher();
    8. teacher.setName("李四");
    9. teacher.setAge(22);
    10. Administrtors admin=new Administrtors();
    11. admin.setName("不良使");
    12. admin.setAge(18);
    13. register(student);
    14. register(teacher);
    15. register(admin);
    16. }
    17. public static void register(Person p){
    18. p.show();
    19. }
    20. }

    Java多态优势是什么

    为了考虑到篇幅和耗时,我们将所有的类写到一个类里面。注意,平时尽量不要这么操作,这里只是为了单纯的图快。

    Test.java

    1. class="prettyprint hljs scala" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo2;
    2. // todo 为了方便查看就不把每一个类分开写了 下面都写到这一个Test.java 文件中
    3. public class Test {
    4. public static void main(String[] args) {
    5. // todo 多态方式创建对象 格式 : Fu fu = new Zi();
    6. Animal animal=new Cat();
    7. // todo 多态方式调用成员变量,编译看左边,运行也看左边
    8. // * 编译看左边 , javac编译的时候会看等号左边父类中有没有这个变量, 如果有编译成功,如果没有,编译失败
    9. // * 运行看左边 , javac编译的时候实际获取的是左边父类中成员变量的值
    10. System.out.println(animal.name); // todo 动物
    11. // 调用成员方法 编译看左边,运行看右边
    12. // * 编译看左边 , javac编译的时候会看等号左边父类中有没有这个变量, 如果有编译成功,如果没有,编译失败
    13. // * 运行看左边 , javac编译的时候实际上运行的是子类中的方法
    14. animal.show(); // todo Cat的show()方法
    15. // 理解
    16. Animal animal1=new Dog();
    17. //现在用animal1是Animal类型,都会默认从Animal这个类中去找
    18. }
    19. }
    20. class Animal{
    21. String name="动物";
    22. public void show(){
    23. System.out.println("Animal的show()方法");
    24. }
    25. }
    26. class Cat extends Animal{
    27. String name="猫";
    28. @Override
    29. public void show() {
    30. System.out.println("Cat的show()方法");
    31. }
    32. }
    33. class Dog extends Animal{
    34. String name="狗";
    35. @Override
    36. public void show() {
    37. System.out.println("Dog的show()方法");
    38. }
    39. }

    省省 1、

    在多态的形式下,右边的对象可以实现解耦合,便于扩展和维护

    例如:

    1. class="prettyprint hljs fsharp" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">Person person = new Student();
    2. person.work(); // 多态new出来的对象调用woek方法

    但是当业务发生了变化时,我需要一个新对象【可以是老师、助教等,但是必须是Person的子类】 只需要修改 new Student();即可

    省省 2、

    定义方法的时候,使用父类型作为参数,可以接收所有子类对象,体现了多态的扩展性于遍历

    任何事物都不是完美无缺的,说完多态的优势,下面我们就来看看多态的劣势吧。

    Java多态劣势是什么

    不能使用子类的特定功能。

    嗯~,其实多态的劣势来源于多态的优势。为什么不修改呢,因为两者是并生的,而多态的优势 > 多态的劣势。任何专业术语,语言特性以及框架的出现都是为了方便性,所以~,你们明白的。

    下面来看看多态的劣势吧!

    我们可以发现animal对象没有找到lookHome()这个方法,是不是很好奇,我明明new的是子类的Dog的对象,为什么Dog类中的方法却不能调用了呢?

    解析:

    多态new出来的对象,在调用成员方法和变量的调用和一般常规new出来的对象有些许不同。

    变量调用: 编译看左边,运行看左边

    编译看左边 , javac编译的时候会看等号左边父类中有没有这个变量, 如果有编译成功,如果没有,编译失败

    运行看左边 , javac编译的时候实际获取的是左边父类中成员变量的值

    方法调用: 编译看左边,运行看右边

    编译看左边 , javac编译的时候会看等号左边父类中有没有这个变量, 如果有编译成功,如果没有,编译失败

    运行看左边 , javac编译的时候实际上运行的是子类中的方法

    产生原因: 多态new出来的对象方法调用 编译看左边,运行看右边 。而父类没有这个方法,所以new出来的对象自然找不到。承受的范围大了。

    解决方案: 向下转型就行了,但是需要注意的是向下转型是不可以随便转的,佛则会报错。

    Test.java

    1. class="prettyprint hljs java" style="padding: 0.5em; font-family: Menlo, Monaco, Consolas, "Courier New", monospace; color: rgb(68, 68, 68); border-radius: 4px; display: block; margin: 0px 0px 1.5em; font-size: 14px; line-height: 1.5em; word-break: break-all; overflow-wrap: break-word; white-space: pre; background-color: rgb(246, 246, 246); border: none; overflow-x: auto; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;">package DT.demo3;
    2. public class Test {
    3. public static void main(String[] args) {
    4. // 堕胎方式创建对象
    5. Animal animal=new Dog();
    6. Dog dog=(Dog)animal;
    7. dog.lookHome();
    8. }
    9. }
    10. class Animal{
    11. public void eat(){
    12. System.out.println("动物在吃饭");
    13. }
    14. }
    15. class Dog extends Animal{
    16. // 继承重写父类Animal的eat方法
    17. @Override
    18. public void eat() {
    19. System.out.println("够吃骨头");
    20. }
    21. // 狗自带方法,父类没有
    22. public void lookHome(){
    23. System.out.println("狗看家");
    24. }
    25. }
    26. class Cat extends Animal{
    27. // 继承重写父类Animal的eat方法
    28. @Override
    29. public void eat() {
    30. System.out.println("猫吃鱼");
    31. }
    32. // 猫自带方法,父类没有
    33. public void catchMouse(){
    34. System.out.println("猫抓老鼠");
    35. }
    36. }

  • 相关阅读:
    docker的简单使用
    文件服务器审核
    Verilog语言中case、casex、casez的用法和区别
    Windows10下局域网的两台电脑间传输文件,设置文件夹共享
    GC-垃圾回收
    Controller统一异常处理和yaml配置
    Android——gradle构建知识片-散装版
    904. 水果成篮(滑动窗口)
    计算机毕业设计springboot基于springboot的游戏交易网络无忧3op09源码+系统+程序+lw文档+部署
    通过WinSCP实现Windows给Ubuntu(Linux)虚拟机传输数据
  • 原文地址:https://blog.csdn.net/Java_ttcd/article/details/126222155