众所周知,Java是一门面向对象的语言。如果我们要设计多种多样的交通工具,比如汽车、火车、飞机,虽然这些工具功能不同、形态不同,但是他们很多的基本功能相同,比如——载人,行驶,是否能飞…,于是我们把class Vehicle(交通工具类)当作设计交通工具的标准,再通过这个标准创建不同的交通工具,包括汽车、火车、飞机等等(class Car,class Train,class Air…),这些工具的共有属性都是继承设计标准(class Vehicle)中的属性。所谓继承,就是将Vehicle类中的部分属性和功能改变,但是大体框架相同,构成新的汽车类(class Car)、火车类(class Train)、飞机类(class Air)。
现在有一个交通工具制造厂;
制造场可以制造汽车、火车、飞机三类交通工具;
制造场可以展示三类交通工具的信息;
汽车:name,capacity,length,tyreNum(型号,载客量,长度,轮胎的个数)
火车:name,capacity,length,haveTrack(型号,载客量,长度,是否有轨道)
飞机:name,capacity,length,haveWing(型号,载客量,长度。是否有机翼)
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+"米");
}
}
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;
}
@Override
public void showInfo(){
super.showInfo();//super关键字,调用父类Vehicle中的showInfo方法
System.out.println(",轮胎数量是:"+tyreNum);
}
}
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;
}
@Override
public 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;
}
@Override
public void showInfo(){
super.showInfo();
System.out.println(",是否有机翼:"+haveWing);
}
}
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();
}
}
}
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();
}
}
在上述例子中,我们可以看到继承的基本操作,那么与继承关系紧密的另一个概念是什么呢?那就是多态了。面向对象的三个基本特征就是:封装,继承,多态。
封装最好理解了。
封装是面向对象的特征之一,是对象和类概念的主要特性。封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
继承的基本概念在上面我已经演示过了,现在详细说说。
继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。通过继承创建的新类称为“子类”,被继承的类称为“父类”。在Java语言中,默认继承,Object父类。继承的过程,就是从一般到特殊的过程。
接下来到了新概念——多态。
多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
实现多态,有二种方式,覆盖,重载。
覆盖,是指子类重新定义父类的虚函数的做法。
重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。
继承的机制,引用学长上培训课给我们的总结就是:
多态的机制,引用学长上培训课给我们的总结就是:
那何为造型Cast?
Vehicle v=new Vehicle();
Car c=new Car();
v=c; //可以
c=v; //编译错误!会爆红
除非用向下造型,c=(Car)v; 但是前提是v管理的的确是一个Car的对象思考下面一个问题:
是不是想到了些什么?这三个类如果向上抽取出共同特点,那就是,都有面积,都有周长。而且每个类都要有计算面积、计算周长的方法。那么我们如何让这三个类建立联系呢?其实可以通过建立抽象类和抽象方法实现。
public class Rectangle extends Shape{
protected double length;
protected double width;
public Rectangle(double length, double width) {
this.length = length;
this.width = width;
}
@Override
public double getPerimeter(){
return (length+width)*2;
}
@Override
public double getArea(){
return length*width;
}
}
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;
}
@Override
public double getPerimeter(){
return sideOne+sideTwo+sideThree;
}
@Override
public 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;
}
@Override
public double getPerimeter(){
return 2*R*Math.PI;
}
@Override
public double getArea(){
return Math.pow((R*Math.PI),2);
}
}
public abstract class Shape {
public abstract double getPerimeter();
public abstract double getArea();
}
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();
//这种情况是不允许存在的,因为抽象的类不能实例化!!!
以上的例子就是由继承引出抽象类和抽象方法,各位可以细品。
在上面了解了抽象之后,我们引入接口的概念:
接口在IDE中有自己的创建(我这里用idea举例)
如何构建呢?
public class Person implements Soundable {
@Override
public void sound(){
System.out.println("你好");
}
}
public class Phone implements Soundable{
@Override
public void sound(){
System.out.println("叮铃铃");
}
}
public interface Soundable {
public void sound();
}
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声明后面。
一个接口能继承另一个接口,和类之间的继承方式比较相似。接口的继承使用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 可能定义或是继承相同的方法。
这些篇幅就直接引用学长上课时候的总结吧:
继承类(不管是实体类还是抽象类)侧重于规则和概念
实现接口侧重于功能(很多able结尾的接口,如Cloneable,Readable,Runable)