一、抽象类
abstract修饰:类和类中的方法
抽象方法:abstract type name(parameter-list);
(abstract不能修饰static方法和构造函数)
引用:抽象类有其引用变量,可以引用任何继承了该抽象类的子类的对象,但抽象类不会有实例对象。
继承:子类继承抽象类时,必须实现超类中的所有抽象方法,否则子类仍为抽象类。
成员:抽象类可以有成员变量(接口只能有常量,抽象类可以有常量,也可以有变量),也可以有具体方法(甚至是静态方法)。
构造函数:抽象类也有构造函数,子类的构造函数必须调用。
注意:抽象类中可以有静态的方法和变量
class A extends B { public static void main(String[] args) { B.show(); System.out.println(B.x); } } abstract class B { static int x = 10; public static void show(){ System.out.println("haha"); } }
抽象类中的静态成员
抽象类和抽象方法的特点:
1.抽象方法一定在抽象类或者接口中
2.抽象方法和抽象类都必须被abstract关键字修饰(接口中的抽象方法可以省略abstract关键字)
3.因为调用抽象方法没有意义,故java规定抽象类不能new对象
4.抽象类中的方法想要被调用,就要由子类重写所有的抽象方法,然后建立子类对象进行调用,如果子类只覆盖了部分抽象方法,该子类肯定也必须还是一个抽象类
5.抽象类中可以全部为抽象方法也可以没有抽象方法(抽象类中可以没有抽象方法,在语法上是可行的)
抽象类的作用场景:
抽象类与一般类并无太大区别,该如何描述事物就如何描述。只不过有些功能,不同的子类有不用的实现内容,就可以把这些方法抽象化,不定义方法主体。
例如:
class Employee extends Person { private double salary; private Date hireday; public Employee(String n, double salary, int year, int month, int day) { super(n); this.salary = salary; GregorianCalendar calendar = new GregorianCalendar(year, month, day); hireday = calendar.getTime(); } public Employee(String n, double salary, int year, int month, int day, int hour,int minute, int second) { super(n); this.salary = salary; GregorianCalendar calendar = new GregorianCalendar(year, month, day, hour, minute, second); hireday = calendar.getTime(); } public double getSalary() { return salary; } public Date getHireday() { return hireday; } @Override public String getDescription() { return "an employee with a salary of $" + salary + '\n' + hireday; } } public class Student extends Person { private String major; public Student(String n, String m) { super(n); major = m; } @Override public String getDescription() { return "a student majoring in " + major; } } public abstract class Person { private String name = "haha"; public Person(String n){ name = n; } public abstract String getDescription(); public String getname(){ return name; } } public class AbstractTest { public static void main(String[] args) { Person[] p = new Person[2]; p[0] = new Employee("Tom", 9000.0, 1999, 1, 10, 19, 20, 21); p[1] = new Student("Jerry", "Math"); for (Person person : p) { System.out.println(person.getDescription()); } } }
抽象类举例
二、接口(比抽象类更抽象的存在)
接口关键字:interface和class同等级
接口的特点:
1.成员变量:全部默认public static final 即静态常量
2.方法:所有方法默认public abstract 即抽象的,声明时不必再写public,实现接口的方法必须声明为public(保持与接口一致)。
实现方法的返回类型和签名必须与接口中定义中定义的一致
(接口中的方法可常量都是可选项,什么都没有的空接口在语法上也是允许的)
3.继承/实现:一个接口可以继承多个接口(类只能单继承类),一个类可以实现多个接口
4.方法实现:接口的实现类必须实现接口中的全部抽象方法,否则其实现类必须是抽象类
5.访问修饰符:默认为包内可访问,public为包外也可(当一个接口被声明为public时,必须位于同名文件中)
(接口是比抽象类更加抽象的存在,不能有实例变量(可以有常量),不能有任何具体方法,是纯粹的抽象)
抽象类和接口的区别:
1.抽象类是类,接口是接口,不是类
2.抽象类中可以有:成员变量,静态常量,抽象方法,具体方法(四选0~4都OK)
接口中只能有:静态常量,抽象方法(至少二选一)
3.接口可以继承(extends)接口,但接口不能继承类/抽象类,而类/抽象类可以实现(implement)接口
4.抽象类和类之间只能单继承,接口之间、接口和类/抽象类可以多继承
5.一个类可以实现多个接口,但是只能继承一个抽象类
总结:抽象类、一般类和接口之间的关系
class A extends B //(1) { char name = 'A'; public static void main(String[] args) { System.out.println("Hello World!"); } } class B extends abstractA //(2) { char name = 'B'; } class C { char name = 'C'; } abstract class abstractA extends C //(3) { String name = "abstractA"; } abstract class abstractB extends abstractA //(4) { String name = "abstractB"; } interface inA { String name = "inA"; } interface inB extends inA,inC //(5) { String name = "inB"; } interface inC { } class D implements inA //(6) { char name = 'D'; } abstract class abstractD implements inB //(7) { String name = "abstractD"; }
抽象类、一般类和接口