抽象:
例如,公司类就为一个抽象类。它的子类有经理类,员工类等。
他们在公司都会工作,但是他们的工作内容不同,所在部门也不同等,因此我们可以构造一个抽象类,不应给出具体的方法实现,只是提供一些方法生明,没有方法体的抽象方法应该定义为抽象方法。具体的实现可以在子类中通过重写来实现。在java中,一个没有方法体的方法应该定义为抽象方法,而类中如果有抽象方法,该类必须定义为抽象类。
关键字:abstract
格式:abstract class 类名{}
特点:A:抽象类不一定有抽象方法,但是有抽象方法的类必须是抽象类。
B:抽象类不能实例化,我们可以按照多态的方式,由具体的子类实例化。
C:抽象类的子类要么是抽象类,要么重写抽象类中的所有抽象方法。
注意:private 因为private 修饰的成员变量,成员函数不能被继承,abstract类存在的前提是有继承关系,两者冲突
Final 是指最后,其修饰的变量,变量就变成常量,只能被赋值一次,修饰类,类不能被继承,修饰方法,方法不能被重写,而abstract类前提是可重写,可继承。两者冲突
Static 没有意义
抽象类的成员特点:
*成员变量
。可以是变量
。也可以是常量
*构造方法
。有构造方法,但是不能实例化。在此构造方法的作用是用来子类访问父类数据的初始化。
*成员方法
。可以有抽象方法,也可以有非抽象方法。
具体的实例和下边的接口一块练习。
接口:比如上述所讲的例子,如果经理类不仅仅重写了该父类的所有的抽象方法,但是有些经理经过了自己的学习还会编程,这些其实本不属于经理类所共有的功能,是部分经理,相当于是扩展的功能。在java中我们就会用接口来定义额外的功能,但是不给出具体的实现,哪些经理想学编程,就去实现该接口就可以,来实现自己的功能扩展。
关键字:interface
接口成员特点:
*成员变量
。只能是常量(默认是public static final修饰)。
*构造方法
。接口中没有构造方法,没有具体的实现,只是扩展功能。
*成员方法
。只能是抽象方法(默认public abstract)
实例:
1、编写java程序,分析如下需求,写出你分析的类有哪些,以及功能。最后写一个测试类,针对每个类的功能进行测试。
我们学校的老师有基础班的,也有就业班的。
共性:
属性:姓名,年龄
功能:讲课。
现在又要针对日语这种小语种单独开班,
需要部分基础班老师和部分就业班老师会说日语。
请用所学知识把上面的内容用代码体现。
创建一个父类Teacher
package cn.edu.xaut2;
public abstract class Teacher {
public String name;
public int age;
public abstract void work();
}
创建一个基础班老师类Baseteacher
package cn.edu.xaut2;
public class BaseTeacher extends Teacher implements Japaninterface{
@Override
public void work() {
System.out.println("我是基础班老师");
}
public BaseTeacher(String name,int age){
this.name=name;
this.age=age;
}
public int getAge(){
return age;
}
public String getName(){
return name;
}
}
创建一个就业班老师类WorkTeacher
package cn.edu.xaut2;
public class WorkTeacher extends Teacher implements Japaninterface{
@Override
public void work() {
System.out.println("我是就业班老师 ");
}
public WorkTeacher(String name,int age){
this.name=name;
this.age=age;
}
public String getName(){
return name;
}
public int getAge(){
return age;
}
}
创建一个测试类Test
package cn.edu.xaut2;
public class Test {
public static void main(String[] args) {
Teacher sa=new WorkTeacher("胡歌",20);
sa.work();
WorkTeacher sc=(WorkTeacher)sa ;
String name=sc.getName();
int age=sc.getAge();
System.out.println("我的名字是 : "+name+" 我的年龄是 :"+age);
Japaninterface an=new WorkTeacher("胡歌", 20);
an.show();
System.out.println("-------------------------------------");
Teacher ss=new BaseTeacher("薛之谦", 26);
ss.work();
Japaninterface ac=new BaseTeacher("薛之谦", 20);
ac.show();
}
}
创建一个接口Japaninterface
public interface Japaninterface {
default void show(){
System.out.println("我会说日语");
};
}
类与类,类与接口以及接口与接口的关系
*类与类
。继承关系,只能单继承,但是可以多层继承
*类与接口
。实现与被实现的关系,可以单实现,也可以多实现,也就是说一个类可以实现多个接口。
*接口与接口的关系
。继承关系,一个接口可以继承多个接口,也可以继承单个接口。
抽象类与接口的区别:
*成员区别
。抽象类 变量,常量,有构造方法,有抽象方法也有非抽象方法
。接口 常量,抽象方法
*关系区别
。类与类 继承,单继承,多层继承
。类与接口 实现,单实现,多实现
。接口与接口 继承,单继承,多继承
注意:抽象类 被继承体现的是:”is a”的关系。共性功能
接口 被实现体现的是:”like a”的关系。扩展功能
实例:猫和狗都是动物,两者都会吃饭,睡觉,但是方式不同,但是有些狗就会通过后天培训会计算,会表演。请你用学过的知识实现。
分析:首先狗和猫都是动物,两者有公共的方法为吃饭,睡觉,因此我们可以定义一个动物类为抽象类,将eat()和sleep都定义为抽象方法,在各自的类中去重写,对于有些狗会计算,会表演,我们可以定义接口来实现。
具体代码如下:
创建一个Animal类
public abstract class Animal {
String name;
int age;
public abstract void eat();
public abstract void sleep();
}
创建一个猫类
public class Cat extends Animal {
@Override
public void eat() {
System.out.println("猫喜欢吃鱼");
}
@Override
public void sleep() {
System.out.println("猫睡觉");
}
}
创建一个狗类
public class Dog extends Animal implements Interface1,Interface2{
//一个类可以继承多个接口,称为多继承。
@Override
public void eat() {
System.out.println("狗喜欢吃肉");//重写方法
}
@Override
public void sleep() {
System.out.println("狗睡觉");
}
@Override
public void show() {
System.out.println("狗还会表演节目");
}
@Override
public void calculate() {
System.out.println("狗还会计算");
}
}
创建一个接口Interface1
public interface Interface1 {
public abstract void calculate();
}
创建一个接口interface2
public interface Interface2 {
public abstract void show();
}
创建一个测试类
public class Test {
public static void main(String[] args) {
Animal an=new Dog();//利用多态来创建对象
an.eat();//调用子类重写的方法
an.sleep();
Interface1 sa=new Dog();
sa.calculate();//实现某些狗类的扩展功能;
Interface2 sd=new Dog();
sd.show();
}
}
注意:在JDK1.7之前 我们的接口中 只能有抽象方法
在JDK1.8之后 接口中 可以定义抽象方法,也可以定义 默认方法,可以定义静态方法
创建一个person 类为父类
public abstract class Person {
public abstract void show();
public static void hehe() {
System.out.println("这是一个类中的静态方法");
}
}
创建一个类为子类student1
public class Student1 implements Interface1,Interface2{
@Override
public void show() {
System.out.println("接口1中的show()方法");
}
@Override
public void print() {
System.out.println("重写了两个接口中同名的默认方法");
}
}
创建一个子类为student
public class Student extends Person implements Interface1{
@Override
public void show() {
System.out.println("展示子类");
}
}
创建一个接口类Interface1
public interface Interface1 {
//jdk1.8可以定义三种形式
public abstract void show();//1.定义抽象方法
default void print(){
System.out.println("这是接口1中的默认方法");//2.定义默认方法
};
public static void hehe(){
System.out.println("这是接口1中的静态方法");//3.定义静态方法
}
}
创建一个接口类Interface2
public interface Interface2 {
default void print(){
System.out.println("这是接口2中的默认方法");
}
}
创建一个测试类Test
public class Test {
public static void main(String[] args) {
Interface1 sa=new Student1();
sa.print();//当两个接口中的默认方法同名时,必须重写这个方法。
Person aa=new Student();
aa.hehe();//当类和接口都有这个方法时,以类优先原则执行程序。
}
}
结果:重写了两个接口中同名的默认方法
这是一个类中的静态方法
总结:A:在JDK1.8中接口可以定义三种类型方法:抽象方法,默认方法,静态方法
在JDK1.7之前只能定义抽象方法
B:当个子类的父类和他所实现的接口中有同明方法时,应该采用类优先原则
C:当一个子类,实现了两个接口,其有同名的默认方法,那么在该类中就必须重写这个方法,在实际的调用中其实也就调用的是该类重写的方法。
总结:接口和抽象类我们最重要的是要从思想上先去理解两者的不同,建立在继承和多态的基础上。