一:抽象
1:引子
在现实中有各种各样的图形,他们都有面积和周长这样的概念,如果在Java中实现计算各种图形的周长,我们可以定义一个类,里面有许多属性,及一个计算周长的方法,然而我们又不能在这一个方法中把所有图形的周长分别罗列出来,这时我们可以采用抽象类来实现。
2:何为抽象
抽象类是从多个具体类中抽象出来的父类,它具有更高层次的抽象,从多个具有相同特征的类中提炼出抽象类,其具体实现,有继承他的子类去实现。
3:何时抽象
在以下任一条成立时,类必须为抽象类
(1)类中至少有一个抽象方法;
(2)类中继承了父类的抽象方法,但至少有一个抽象方法没有实现
(3)类中实现了某一个接口,但没有全部实现接口中的方法
4:如何定义
[修饰符] abstract class 类名{//类体}
5:特别注意:
(1)抽象类中的方法可以具体实现,也可以不实现,这里的实现指的是方法有方法体,里面可以什么都不做,也可以是一个普通的方法。不实现的方法让子类去实现,子类可以实现也可以不实现,如果子类不实现,则子类也是一个抽象类
(2)如果一个类有没有实现的方法即抽象方法,则这个类必须为抽象方法
(3)任何一个类都有构造方法,抽象类也是,只是因为抽象类中存在没有具体实现的方法,所以不能实力化具体的对象,即不能通过new +抽象类类名的形式创建对象。其构造方法是让子类来调用的
(4)抽象类的使用是采用多态的形式来实现的
6:具体使用
◆定义抽象父类Shape,提供计算周长的方法
public abstract class Shape {//注意关键字 public abstract double calPermieter();//定义抽象方法,没有方法体 }
◆定义矩形子类,继承抽象父类Shape,提供自己的属性,及实现父类的抽象方法
public class Rectangle extends Shape{//注意extends关键字 private double width; private double height; public Rectangle() { super(); } public Rectangle(double width, double height) { super(); this.width = width; this.height = height; } //抽象方法的具体实现,根据子类的计算规则去实现 @Override public double calPermieter() { return 2*(this.width+this.height); } }
◆定义圆形类,继承抽象父类Shape,提供自己的属性及计算规则
public class Circle extends Shape{ private double r; //半径属性 public Circle(double r) { super(); this.r = r; } public Circle() { super(); } //根据自己的计算规则实现继承来的抽象方法 @Override public double calPermieter() { return 2*Math.PI*this.r; } }
◆测试类,注意具体的使用哦
public class Test { public static void main(String[] args) { Shape s1 =new Rectangle(20,30);//运用多态实现具体的使用 double c1 = s1.calPermieter();//矩形的周长的方法的使用 System.out.println("矩形的周长为:"+c1); Shape cir1 =new Circle(30);//运用多态实现具体的使用 double c2 = cir1.calPermieter();//圆形的周长的方法的使用 System.out.println("圆形的周长为:"+c2); // Shape s3 = new Shape();抽象类不能创建子类对象,应通过子类的构造运用多态来实现 } }
◆结果:
矩形的周长为:100.0 圆形的周长为:188.49555921538757
二:接口
1:何为接口
接口作为类与外界交互的窗口,提供的是一种规范,对于接口的实现者而言,接口规范了实现者必须提供的服务。通俗的说,就是电脑后面的显示器接口,说明了他只能接一个显示器,而没有具体的实现,只有接上了显示器才具有显示的功能。
2:定义接口
与java中的类不一样,接口的定义采用的是interface关键字。如下:
[访问修饰符] interface 接口名 [继承父接口]{
//0到多个常量
//0到多个抽象方法
}
3:接口的继承
在Java中类只能实现单继承,且只能实现一个接口。然而,接口也可以实现继承,同样使用extends关键字去继承一个或多个父接口(用逗号隔开),达到多继承,从而弥补类中只能实现的单继承 。定义如下:
[访问修饰符] interface 接口名 [继承父接口] extends[父接口,父接口,父接口]{
//0到多个常量
//0到多个抽象方法
}
4:特别注意
(1)接口中属性值默认的情况下为且只能为public static final的,接口中的方法默认的情况下为且只能为public abstract 类型的,
(2)由此可见接口中的方法必须在实现接口的类中去实现,即接口中的方法没有实现,只提供了定义,实现接口的类必须实现所有的抽象方法
(3)接口中没有main方法,因为main方法有具体的实现
(4)接口中没有构造方法,不能通过new 创建对象,只能通过子类来实现
(5)java中的类与接口之间的相互关系
类----类:单继承,extends 接口----接口:多继承/单继承,extends 类----接口:实现,implements
(6)类之间的强制转换时,会检测类之间的继承关系,而转换为接口时不会检测实现关系
5:具体使用:
◆定义接口
public interface TestInterface{ int MAX_NUM=1000;//接口中的属性,默认为static final类型 void test();//接口中的方法,默认为abstract类型的 }
a:验证属性的默认类型
public class Test implements TestInterface{//注意implements关键字的使用 @Override public void test() {//必须实现的方法,否则编译时异常,说明在接口中是抽象方法 System.out.println("我是接口中的抽象方法"); } public static void main(String[] args) { System.out.println("我是接口中的静态不可变常量:"+TestInterface.MAX_NUM); //可以直接使用接口名.属性名来获取属性值,说明属性值是static修饰的 // TestInterface.MAX_NUM=10009;编译时异常,说明这个属性值不可以改动,所以为final修饰的 } }
结果:
我是接口中的静态不可变常量:1000
b:接口的多继承
◆定义电话,听,说的三个接口,让电话具备听和说的双重功能
public interface Phone extends Listen,Say{ //定义Phone接口,继承了下面的两个接口,说明它具有听和说的双重功能 } interface Listen{ //定义”听“接口,表明实现该接口的类或继承该接口的接口具有听的功能 } interface Say{ //定义”说”接口,表明实现该接口的类或继承该接口的接口具有说的功能 }
c:接口的使用
接口可以被类实现被接口继承,实现接口的类的定义
[访问修饰符] class 类名 [extends 父类] implements接口1,接口2{//代码块}
◆定义接口,提供学习的功能
public interface Study{ public abstract void study();//抽象方法 }
◆定义具体的实现接口的类
public class Person implements Study{ public void study() { System.out.println("我是实现接口的Person类,所以必须实现接口中的抽象方法"); } public static void main(String[] args) { Person p = new Person();//创建具体实现类的对象 p.study();//调用实现的方法 } }
◆结果:
我是实现接口的Person类,所以必须实现接口中的抽象方法
三:接口与抽象
1:共同特征
(1)都不能被实例化。
(2)都包含抽象方法。继承抽象类的类可以选择实现或者不实现,不实现则子类为抽象类,实现接口的类必须实现接口中所有的抽象方法
2:二者区别
(1)接口中只能有抽象方法,抽象类中至少有一个抽象方法
(2)接口中不能定义静态方法,抽象类中则可以定义静态方法
(3)接口中的属性只能是静态常量,不能有普通属性,抽象类中则可以定义普通属性及静态常量
Java中还有很多这样的难以区分的东西,熟练理解,才是硬道理。