目录
接口(interface)和抽象类(abstract)的区别
抽象类
1.方法覆写
这里先了解方法覆写(override)相关概念
概念
在有继承关系的类之间,子类定义了和父类完全相同的方法(方法名称同,参数相同,返回值同或是向上转型类的返回值,子类权限>=父类权限)
与方法重载的对比
方法重载(overload):与重写两个概念,是在相同的类中,定义了若干个方法名称相同,参数列表不同(参数类型,个数)的方法
方法覆写的要求
1.只能重写成员方法,不能重写静态方法(重载可以写静态方法)
2.子类方法的权限修饰符>=父类
⭐(坑):当子类和父类不在一个包中,并且两个都是包访问权限时,不能正确覆写--why?
Dog在animal1包中,Animal在animal包中
package java_1_10.animal;
public class Animal {
public String name;
public Animal(String name){
this.name=name;
}
void eat(String food){
System.out.println("动物"+this.name+"正在吃"+food);
}
}
package java_1_10.animal;
import java_1_10.Animal1.Dog;
public class Test {
public static void main(String[] args) {
Animal animal=new Animal("动物");
animal.eat("食物");
Animal dog=new Dog("二哈");
dog.eat("狗粮");
}
}
package java_1_10.Animal1;
import java_1_10.animal.Animal;
public class Dog extends Animal {
public Dog(String name) {
super(name);
}
void eat(String food){
System.out.println("狗狗"+this.name+"正在吃"+food);
}
}
对于包访问权限来说,只对当前包同级目录下的类之间可见,对于不同包的animal和dog来说,dog类压根不知道animal还有eat方法,所以无法覆写
3.方法覆写返回值必须相同,至少是向上转型的返回值
题目⭐
class A{
public A(){
this.func();
}
public void func() {
System.out.println("A 的 func");
}
}
public class B extends A{
private int num=10;
public B(int num){
this.num=num;
}
public void func(){
System.out.println("B 的 func.num="+num);
}
public static void main(String[] args) {
new B(100);
}
}
结果:B 的 func.num=0
分析:主方法中传入B类对象,B继承A类,所以调用A类构造方法(题目有隐藏的向上转型),A构造方法中调用了func方法(B中也有覆写),而看func调用的是哪个方法,要看new的谁,newB,所以调用了B中的func方法。而此时程序还是卡在public A的无参构造这一步的,所以B中的num还没有初始化与赋值,所以num仍是0。
总结:Animal animal=new Cat();animal能调用什么方法是Animal决定的;animal调用的方法到底是哪个类的方法,要看new在哪。
2.抽象类的概念
抽象类是普通类的超集,比普通类只是多了些抽象方法。抽象方法是对子类做出方法覆写的强制性要求的方法,即子类(普通子类)若要继承抽象类,必须覆写抽象类中所有抽象方法【注意:子类若也是抽象类,可以选择不覆写父类的抽象方法】
abstract关键字
java中,使用abstract关键字描述抽象类与抽象方法,抽象方法所在类一定是抽象类
public abstract class Sharp{//抽象类
public abstract void print();//抽象方法
public void println(){}//普通方法
}
3.抽象类三个原则
1.抽象类无法直接实例化对象,需要通过向上转型实例化。子类(普通子类)继承抽象类,必须覆写抽象类中所有抽象方法。
Sharp sharp=new Sharp();//❌
Sharp sharp=new XingxingSharp();//✔✔
2.抽象类仍有构造方法,普通方法等(普通类有的,抽象类也有),子类仍然遵循对象的实例化流程(先调用父类构造方法)
3.final abstract可否同时出现?private abstract可否同时出现?
不能。final修饰的类不能有子类,而abstract修饰的类必有子类,矛盾;private修饰的方法只当前类内部可见,说明子类无法覆写,abstract修饰的抽象方法必须被覆写,矛盾,所以不可。
4.抽象类的意义与局限
意义
抽象类最大意义就是强制要求子类(子类是普通类时)必须覆写抽象方法,保证多态正确运行。
局限
1.子类继承抽象类,仍然满足is a原则(继承原则)(接口不遵循)
2.抽象类仍然是类,是单继承局限,一个类(子类)只能继承一个抽象类(父类)
接口
由于接口的局限,应用场景不多,也就提出了更混合的结构:接口
1.接口的定义与实现
定义:interface关键字
Java中使用interface关键字定义接口,接口中只有全局常量和抽象方法(JDK8之前,JDK8扩展了default方法)