当编写一个类时,我们往往会为该类定义一些方法,这些方法是用来描述该类的行为方式,那么这些方法都有具体的方法体。但是有的时候,某个父类只是知道子类应该包含怎么样的方法,但是无法准确知道子类如何实现这些方法。
抽象方法的定义:通过 abstract
关键字来修饰的类称为抽象类;
abstract class A{}
注意:
abstract class Person{}
class Student extends Person{}
public class Demo2 { public static void main(String[] args) { Person p = new Student();//体现的是多态,父类声明实例化子类对象。而不是抽象类实例化 }}
是被 abstract
修饰的方法。抽象方法只有返回类型和方法签名,没有方法体。
public abstract void fun1();
[非private访问修饰符] abstract 返回值类型 方法名称(参数列表);
abstract class Person3{ abstract void show(); abstract void inof(); void turn(){ }}
class NewP extends Person3{ @Override void show() { }
@Override void inof() { } //不覆写的话会报错}
public class Demo15 { public static void main(String[] args) { //new Person3();报错!因为抽象类不可以实例化 }}
抽象类是多个具体子类抽象出来的父类,具有高层次的抽象性;以该抽象类作为子类的模板可以避免子类设计的随意性; 抽象类作为多个子类的通用模板,子类在抽象类的基础上进行拓展,但是子类在总体上大致保留抽象类的行为方式; 编写一个抽象父类,该父类提供了多个子类的通用方法,并把一个或多个抽象方法留给子类去实现,这就是模板设计模式;
//模板模式
//抽象类中包含很多的抽象方法,子类必须去覆写!abstract class Method{ abstract double mul();//返回值类型如果是void的话,下面报错,因为没有返回值,无法引用! abstract double divid(); void show(){ System.out.println("面积是:"+mul());//周长 System.out.println("面积是:"+divid());//面积 }}
class Square extends Method{ double d;
public Square(double d) { super(); this.d = d; }
@Override double mul() { return d * d; }
@Override double divid() { return 4 * d; }}
class Cirle extends Method{ double r;
public Cirle(double r) { super(); this.r = r; }
@Override double mul() { return 2 * 3.14 * r; }
@Override double divid() { return 3.14 * r * r; }}
public class Demo16 { public static void main(String[] args) { Square s = new Square(5); s.show(); Cirle c = new Cirle(4); c.show(); }}
抽象类是从多个类中抽象出来的模板,若要将这种抽象进行得更彻底,就得用到一种特殊的“抽象类”→ 接口;
例子:生活中听说过的USB接口其实并不是我们所看到的那些插槽,而是那些插槽所遵循的一种规范; 而我们看到的那些插槽是根据USB规范设计出来的实例而已,也就说插槽是USB的实例; 对应不同型号的USB设备而言,他们各自的USB插槽都需要遵循一个规范,遵守这个规范就可以保证插入插槽的设备能与主板正常通信; 对于同一种型号的主板上的多个USB插槽,他们有相同的数据交换方式,相同的实现细节,可认为他们都是同一个类的不同实例
总结:
好处:
接口定义一种规范,规定一个类必须做什么,但它不管如何具体去做;
[修饰符] interface 接口名 extends 父接口1,父接口2....
public interface IService { public abstract void fun1();
}
注意
publicabstract
可以省略不写publicstaticfinal
静态常量格式: publicclassSubImplextendsSuperimplementsIA,IB
让类实现接口,可以实现多个接口,实现的接口必须实现接口中所有的方法。
interface IA { void a();}
interface IB { void b();}
class ABImpl implements IA, IB {
@Override public void a() { System.out.println("a"); }
@Override public void b() { System.out.println("b"); }}
public class InterfaceDemo { public static void main(String[] args) { //接口不能创建实例,但是可以声明引用类型的变量。 IA ia = new ABImpl(); IB ib = new ABImpl();
ia.a(); ib.b(); }}
相同点:
不同点:
二者的选用:
格式:
new 父类构造器([实参列表]) 或 接口(){//匿名内部类的类体部分}
例如我们将上面代码中IA,IB两个接口通过匿名内部类的方式来创建其对象:
IA innerIa = new IA() { @Override public void a() { System.out.println("inner a"); }};
IB innerIb = new IB() { @Override public void b() { System.out.println("inner b"); }};
innerIa.a();innerIb.b();
特点
//枚举enum Color { Green, Blue, Yellow;
@Override public String toString() { String ret = super.toString(); switch (this) { case Green: ret = "绿色"; break;
case Blue: ret = "蓝色"; break;
case Yellow: ret = "黄色"; break;
default: break; }
return ret; }
}
class Personp { Color c = Color.Blue;
void show() { System.out.println(c); }}
public class Demo18 { public static void main(String[] args) { Color[] color = Color.values(); for (Color c : color) { System.out.println(c); } new Personp().show(); }}输出:绿色蓝色黄色蓝色