Java中的继承、多态和接口

1、用类比引入继承概念

众所周知,Java是一门面向对象的语言。如果我们要设计多种多样的交通工具,比如汽车、火车、飞机,虽然这些工具功能不同、形态不同,但是他们很多的基本功能相同,比如——载人,行驶,是否能飞…,于是我们把class Vehicle(交通工具类)当作设计交通工具的标准,再通过这个标准创建不同的交通工具,包括汽车、火车、飞机等等(class Car,class Train,class Air…),这些工具的共有属性都是继承设计标准(class Vehicle)中的属性。所谓继承,就是将Vehicle类中的部分属性和功能改变,但是大体框架相同,构成新的汽车类(class Car)、火车类(class Train)、飞机类(class Air)。

2、用问题深入什么是继承?

现在有一个交通工具制造厂;
制造场可以制造汽车、火车、飞机三类交通工具;
制造场可以展示三类交通工具的信息;
汽车:name,capacity,length,tyreNum(型号,载客量,长度,轮胎的个数)
火车:name,capacity,length,haveTrack(型号,载客量,长度,是否有轨道)
飞机:name,capacity,length,haveWing(型号,载客量,长度。是否有机翼)

3、用代码演示继承的作用

  1. 首先,观察问题,汽车、火车、飞机都是交通工具,它们的信息都有name,capacity,length,所以我们构建一个class Vehicle(交通工具类),Vehicle类中包含它们三者共有的信息。并且最后都是要输出信息的,所以我们在Vehicle类中也构建一个showInfo的方法。
public class Vehicle {protected String name;protected int capacity;protected int length;public Vehicle(String name , int capacity , int length){this.name = name;this.capacity = capacity;this.length = length;}public void showInfo(){System.out.print(name+"的最大载客量是:"+capacity+",长度是:"+length+"米");}
}
  1. Vehicle类构建完了,接下来构建一个class Car(汽车类)。在这个Car类中,重点来了,我们用extends关键字把Car作为Vehicle类的子类。然后,我们再在Car类中给一个tyreNum整形变量,代表汽车轮胎个数。然后给Car类一个构造器,包括name,capacity,length,tyreNum。重点来了,用super关键字,将形参name,capacity,length,给定到父类Vehicle中,而Car类专属的tyreNum就在本类用。再给定一个showInfo方法,用来展示汽车的信息。重点来了,在showInfo方法中,用super关键字调用Vehicle中的showInfo方法。
public class Car extends Vehicle //extends关键字,表示Car类继承Vehicle类,即Car是Vehicle的子类{protected int tyreNum;public  Car(String name , int capacity , int length , int tyreNum){super(name, capacity, length);//super关键字,将形参传给父类this.tyreNum=tyreNum;}@Overridepublic void showInfo(){super.showInfo();//super关键字,调用父类Vehicle中的showInfo方法System.out.println(",轮胎数量是:"+tyreNum);}
}
  1. 在Car类构建完毕之后,同理,构建出Train类和Air类,分别由自己的专属实例变量,haveTrack和haveWing。代码如下:
public class Train extends Vehicle{protected boolean haveTrack;public Train(String name , int capacity , int length , boolean haveTrack){super(name, capacity, length);this.haveTrack=haveTrack;}@Overridepublic void showInfo(){super.showInfo();System.out.println(",是否有轨道:"+haveTrack);}
}
public class Air extends Vehicle{protected boolean haveWing;public Air(String name , int capacity , int length , boolean haveWing){super(name, capacity, length);this.haveWing=haveWing;}@Overridepublic void showInfo(){super.showInfo();System.out.println(",是否有机翼:"+haveWing);}
}
  1. 在完成以上构建类的步骤之后,我们创建一个交通工具制造厂(class Database),用来进行制造交通工具,并输出交通工具的信息。我们用ArrayLise的方式new一个容器vehicles。构建一个增加交通工具的add方法,目的是将交通工具放入vehicles容器中。再建立一个输出交通工具信息的list方法,用来展现交通工具的信息。
import java.util.ArrayList;public class Database {ArrayList<Vehicle>vehicles=new ArrayList<Vehicle>();public void add(Vehicle vehicle){vehicles.add(vehicle);}public void list(){for(Vehicle v:vehicles){v.showInfo();}}
}
  1. 在完成上述四步之后,我们可以进入测试环节,创造一个测试类用于测试,代码如下:
public class Test {public static void main(String[] args) {Database db=new Database();db.add(new Car("宝马",5,3,4));db.add(new Train("和谐号",1800,500,true));db.add(new Air("客机",500,28,true));db.list();}
}
  1. 运行代码,结果如下:

    我们可以看到,成功运行,并且把信息成功输出!

4、继承的更多和多态的概念

在上述例子中,我们可以看到继承的基本操作,那么与继承关系紧密的另一个概念是什么呢?那就是多态了。面向对象的三个基本特征就是:封装,继承,多态。

  1. 封装最好理解了。
    封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。

  2. 继承的基本概念在上面我已经演示过了,现在详细说说。
    继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”,被继承的类称为“父类”。在Java语言中,默认继承,Object父类。继承的过程,就是从一般到特殊的过程。

  3. 接下来到了新概念——多态。
    多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
    实现多态,有二种方式,覆盖,重载。
    覆盖,是指子类重新定义父类的虚函数的做法。
    重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。

继承的机制,引用学长上培训课给我们的总结就是:

  • 子类调用方法时优先调用自己的,如果自己没有在调用父类的;
  • 子类构造对象时,需要用到super();方法向父类传递对应的参数,并且符合一下顺序:父类构造->子类的定义初始化->构造器初始化
  • 如果不调用super,构造器会自动在父类中寻找不带任何参数的构造器
  • 要在子类的方法中调用父类的方法,需要用到super关键字

多态的机制,引用学长上培训课给我们的总结就是:

  • 子类的对象可以被当作父类的对象来使用

    • 赋值给父类的变量
    • 传递给需要父类对象的函数
    • 放进存放父类对象的容器里
  • Java的所有对象变量都是多态的,它能保存不止一种类型的对象
  • 它们可以保存的是声明类型的对象(静态类型),也可以是声明类型的子类的对象(动态类型)
  • 当我们把一个子类的对象交给父类的变量管理时就发生了向上造型;

那何为造型Cast?

  • 把一个类的实例对象赋值给另外一个类的变量的过程叫做造型

    • 父类的变量可以管理子类的对象(向上造型)
    • 子类的变量不能管理父类的对象
      Vehicle v=new Vehicle();
      Car c=new Car();
      v=c;   //可以
      c=v;   //编译错误!会爆红
      

      除非用向下造型,c=(Car)v; 但是前提是v管理的的确是一个Car的对象

  • 向上造型总是安全的,是默认的,不需要加括号
  • 向下造型是强制的,是不安全的,可能会发生异常
  • 造型不是类型转换

5、由继承引入抽象类和抽象方法(abstract)

思考下面一个问题:

  • 现在需要做三个类
  • 矩形,三角形,圆形
  • 每个类里面都需要有计算周长的方法getPerimeter(); 和计算面积的方法getArea();

是不是想到了些什么?这三个类如果向上抽取出共同特点,那就是,都有面积,都有周长。而且每个类都要有计算面积、计算周长的方法。那么我们如何让这三个类建立联系呢?其实可以通过建立抽象类和抽象方法实现

  1. 我们首先创建矩形类(class Rectangle),在矩形类中创建构造器和计算周长的方法getPerimeter();和计算面积的方法getArea()。
public class Rectangle extends Shape{protected double length;protected double width;public Rectangle(double length, double width) {this.length = length;this.width = width;}@Overridepublic double getPerimeter(){return (length+width)*2;}@Overridepublic double getArea(){return length*width;}
}
  1. 同理,我们随之建立三角形类(class Triangle)和圆类( class Circular),在类中创建构造器和计算周长的方法getPerimeter();和计算面积的方法getArea()。
public class Triangle extends Shape{protected double sideOne;protected double sideTwo;protected double sideThree;public Triangle(double sideOne, double sideTwo, double sideThree) {this.sideOne = sideOne;this.sideTwo = sideTwo;this.sideThree = sideThree;}@Overridepublic double getPerimeter(){return  sideOne+sideTwo+sideThree;}@Overridepublic double getArea(){double p=(sideOne+sideTwo+sideThree)/2.0;return Math.sqrt(p*(p-sideOne)*(p-sideTwo)*(p-sideThree));}
}
public class Circular extends Shape{double R;public Circular(double r) {R = r;}@Overridepublic double getPerimeter(){return 2*R*Math.PI;}@Overridepublic double getArea(){return Math.pow((R*Math.PI),2);}
}
  1. 你会发现上面三段代码的共同点 extends Shape,那么这个class Shape是何方神圣呢?
public abstract class Shape {public abstract double getPerimeter();public abstract double getArea();
}
  1. 非常简短的代码,只不过多了一个关键字abstract。这个关键字是抽象的意思,在abstract的类中,不能有具体的方法。我们上面的三种形状都是Shape的子类。那么我们创造一个test类来测试一下!
public class test {public static void main(String[] args) {Shape R=new Rectangle(10,15);Shape T=new Triangle(3,4,5);Shape C=new Circular(5);System.out.println(R.getArea());System.out.println(R.getPerimeter());System.out.println(T.getArea());System.out.println(T.getPerimeter());System.out.println(C.getArea());System.out.println(C.getPerimeter());}
}


这里要注意的问题是,抽象类不能实例化!

Shape shape=new Shape();
//这种情况是不允许存在的,因为抽象的类不能实例化!!!

以上的例子就是由继承引出抽象类和抽象方法,各位可以细品。

6、抽象的接口

在上面了解了抽象之后,我们引入接口的概念:

  • 接口(英文:Interface),在JAVA编程语言中是一个抽象类型,是抽象方法的集合,接口通常以interface来声明。一个类通过继承接口的方式,从而来继承接口的抽象方法。
  • 接口并不是类,编写接口的方式和类很相似,但是它们属于不同的概念。类描述对象的属性和方法。接口则包含类要实现的方法。
  • 除非实现接口的类是抽象类,否则该类要定义接口中的所有方法。
  • 接口无法被实例化,但是可以被实现。一个实现接口的类,必须实现接口内所描述的所有方法,否则就必须声明为抽象类。另外,在 Java 中,接口类型可用来声明一个变量,他们可以成为一个空指针,或是被绑定在一个以此接口实现的对象。

接口在IDE中有自己的创建(我这里用idea举例)


为了更了解接口,下面由一个问题引入:

  • 现在有一个手机类Phone,和人类Person
  • 两者都有发出声音的方法Sound();
  • 我们想把这个公共的方法提取出来但是又不违和;

如何构建呢?

  1. 我们建立人类和手机类
public class Person implements Soundable {@Overridepublic void sound(){System.out.println("你好");}
}
public class Phone implements Soundable{@Overridepublic void sound(){System.out.println("叮铃铃");}
}
  1. 建立Soundable接口
public interface Soundable {public void sound();
}
  1. 创建测试类
public class test {public static void main(String[] args) {Soundable person=new Person();Soundable phone=new Phone();person.sound();phone.sound();}
}

结果如下:

此外,又因为接口本身就是抽象的,所以下面两个没区别(有无abstract)

public abstract interface Soundable {public abstract void sound();
}
public interface Soundable {public void sound();
}

还有,当类实现接口的时候,类要实现接口中所有的方法。否则,类必须声明为抽象的类。类使用implements关键字实现接口。在类声明中,Implements关键字放在class声明后面。

7、接口的继承

一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用extends关键字,子接口继承父接口的方法。

接着举个例子吧,下面的Sports接口被Hockey和Football接口继承:

public interface Sports
{public void setHomeTeam(String name);public void setVisitingTeam(String name);
}
public interface Football extends Sports
{public void homeTeamScored(int points);public void visitingTeamScored(int points);public void endOfQuarter(int quarter);
}
public interface Hockey extends Sports
{public void homeGoalScored();public void visitingGoalScored();public void endOfPeriod(int period);public void overtimePeriod(int ot);
}

Hockey接口自己声明了四个方法,从Sports接口继承了两个方法,这样,实现Hockey接口的类需要实现六个方法。相似的,实现Football接口的类需要实现五个方法,其中两个来自于Sports接口。

此外,接口可以多继承,在接口的多继承中extends关键字只需要使用一次,在其后跟着继承接口。 如下所示:

public interface Hockey extends Sports, Event

以上的程序片段是合法定义的子接口,与类不同的是,接口允许多继承,而 Sports及 Event 可能定义或是继承相同的方法。

8、接口的总结

这些篇幅就直接引用学长上课时候的总结吧:

接口的一些机制

  • 接口里的所有方法都是抽象方法,即使前面没有加abstract声明,系统会自动默认
  • 接口里的所有变量都是静态变量
  • 接口可以继承接口,但不能继承类
  • 接口不能有实体
  • 一个类可以实现多个接口,实现 用关键字 implements

接口存在的意义

  • 将某个功能抽象出来,提高可扩展性
  • 是Java成功的关键之一,因为极适合多人写一个大程序
  • 也是Java被批评的要点之一,因为容易造成代码膨胀

继承类(不管是实体类还是抽象类)侧重于规则和概念
实现接口侧重于功能(很多able结尾的接口,如Cloneable,Readable,Runable)

9、总结与感想

  • 其实这篇博文,很多概念我都是在写的时候更进一步的弄清楚的,继承、多态、接口,许许多多的知识在查阅的时候才会更多的灌输到脑子里。当然,敲代码举例子也是很不错的过程。如果对我这篇文章很多概念还是没有弄清楚的,可以参考 Java继承 和 Java多态 还有 Java接口 ,或者是看看其他的有关博文。
  • 当然,这篇博文对我而言不仅仅是一项任务,更像是一次自我提升,在查资料、敲代码、写博文,这三步之后,我感觉我的基础框架构建出来了。古人云,授人以鱼不如授人以渔。而我发现,在授人以渔的过程中,自己的进步是真的很大,比起刷网课视频,自己实践动手给人更多的提升感觉,尽管过程很苦很累,但是一切都是值得的!写下这篇博文,更像是给自己做一份笔记,让自己了解更细致,这钟感觉针不戳~
  • 还望未来的自己再接再厉,继续前行!

【Java】继承、多态、接口相关推荐

  1. Java继承多态经典案例分享

    今天动力节点java培训机构小编为大家分享Java继承多态经典案例,希望通过此文能够帮助到大家,下面就随小编一起看看Java继承多态经典案例. public class A { public Stri ...

  2. Java继承同时实现接口 以及继承方法的使用

    Java继承同时接口的实现: 代码如下 interface Achievement {public float avarage(); }class Person {String name;int ag ...

  3. java抽象 继承 多态 接口

    **继承:**继承就是子类继承父类的特征和行为,使得子类对象(实例)具有父类的实例域和方法,或子类从父类继承方法,使得子类具有父类相同的行为 public class mp3 {private Str ...

  4. (十)Core Java 面向对象(封装,继承,多态,接口) -02 (96)

     目录 :        24 ). 面向对象(聚集关系) 25 ). 面向对象(子父类中变量的特点) 26 ). 面向对象(子父类中函数的特点-覆盖) 27 ).  面向对象(子父类中构造函数的特点 ...

  5. java练习题(面向对象前两天练习作业(继承多态接口和抽象类))

    1. [编号:1001]一位面向对象的程序员小李,在编程过程中需要描述和处理个人信息,于是定义了类Person,如下所示: public class Person {private String na ...

  6. 猿创征文 |【JAVA小程序】图书管理系统(继承 多态 接口 链表 一应俱全)附源码

    谢谢你陪着稀奇古怪的我 大家好,这里是新一,请多关照

  7. java继承和接口的优缺点_Java抽象类和接口的优缺点---总结-2

    51Testing软件测试网[P/WX?\ 解决方案二:~+j;Hw/U1{@4g0 A^9@5]p7j:Rys0既然open.close和alarm属于两个不同的概念,根据ISP原则应该把它们分别定 ...

  8. java继承和接口的区别_继承和实现接口的区别

    1,java类可以一次继承多个接口,用implements 接口1,接口2 2,如果是接口继承接口的话也可以用extends,接口是多继承的,java类才是单继承 3,接口继承接口可以不实现父接口中的 ...

  9. java 继承多态的一些理解和不理解

    1.向上转型的一个误区 一直以为Child 继承Parent以后, Parent p = new Child();  p可以调用Child类中拓展Parent的方法,原来必须在强制转换成Child类才 ...

  10. Java继承,接口,抽象类

    继承 继承的例子: class Father {public void f1(){System.out.println("hi");} }public class Son exte ...

最新文章

  1. JavaEE Web开发之Servlet篇
  2. 自然语言处理笔记4-哈工大 关毅
  3. TCP/IP协议简介2
  4. Send mail via http client - CL_SAM_SESSION_QUEUE_SENDER
  5. 7-11 租用游艇问题 (15 分)(思路+详解+一步步分析+网格解决动态规划问题)Come boy!!!!
  6. uva 11054——Wine trading in Gergovia
  7. matlab simulink 汽车制动纵向动力学建模
  8. 荔枝软件如何测试声音,荔枝如何测自己的声音 荔枝测自己的声音方法
  9. 渗透测试工程师面试题大全(164道)
  10. Macbook Pro 扩展内存
  11. 关于ArcGIS新建Person Geodatabase(.mdb)报错的问题
  12. 《代码大全2》第3章 三思而后行,前期准备
  13. 深度学习论文: Rethink Dilated Convolution for Real-time Semantic Segmentation及其PyTorch实现
  14. GMap2 与 google.maps.Map 的区别
  15. 在MySQL中 NULL的含义是_mysql null的含义是什么
  16. 小贾同学博客园开通啦
  17. 华为Ascend昇腾CANN详细教程(二)
  18. 小米6X计算机在后台程序无法关闭,小米6怎么关闭后台程序教程
  19. Angular页面截图(滚动条显示完整)
  20. 解决虚拟机安装系统报错解决方法

热门文章

  1. pyinstaller 打包exe 防反编译(加密)
  2. 野田圣子、希尔顿、松下幸之助,都喝过马桶水吗? .
  3. 微信小程序开发实战9_3 小程序URL Scheme
  4. kolla 部署openstack train版本(三节点controller+compute+storage)------功能测试
  5. python interpreter配置_PyCharm使用之配置SSH Interpreter
  6. vue如何新建一个项目(详细步骤)
  7. 利用TUN创建虚拟网络
  8. 中国象棋棋盘c语言编程,中国象棋 C语言编程.ppt
  9. ios让您的today变得更加有节奏,新出品Today:日历、提醒、习惯养成、倒计时
  10. java 系统工具类 查询内存 CPU 系统基本信息 SysInfoUtils