在讲接口与抽象类之前,我先更正一下https://blog.csdn.net/weixin_40321672/article/details/79904135这篇博客的错误,
自动转型和强制转型:
假如有Student父类,UNStudent子类。则:
//自动转型
Student un = new UNStudent();
un.setName("Firewall");
un.study();//这里访问的是UNStudent子类中的重写方法
//强制转型
UNStudent unst = (UNStudent)un;
unst.printName(); //这里必须对un进行向下转型,才能访问到UNStudent子类中自己创建的方法,否则报错
自动转型的好处:如果存在一个老师教学生的类,使用自动转型就方便很多
public class Teacher {
public void teach(Student s){
s.study();
}
}//只用传入Student s,然后访问各自子类中的study()方法
Teacher t = new Teacher();
t.teach(unst);
然后,提几个问题:
1.构造方法能被继承吗? 不能直接被继承,可以通过super()调用
2.私有变量和方法被继承了吗? 被继承了,但是无权限访问,可以通过set、get方法进行访问
3.静态方法不能被子类重写?
java编程思想里说的一句话是“只有普通的方法调用可以是多态的”。静态方法可以被继承,但是不能被重写。就算是子类出现了和父类只有方法体不一样其他都一模一样的static方法,也只算是把原来继承过来的父类的方法隐藏,而不是重写,也不会达到多态的目的。本来static方法引用的时候应该用类名来引用,而不是对象,所以也不存在什么多态和重写的说法。
class Father {
public static void staticMethod() {
System.out.println("Father");
}
}
class Son extends Father {
// @Override 因为从逻辑上达不到重写的目的,所以这里添加 @Override 会编译报错
public static void staticMethod() {
System.out.println("Son");
}
}
public class M {
public static void main(String[] args) {
Father mByFather = new Father();
Father mBySon = new Son();
Son son = new Son();
mByFather.staticMethod();
mBySon.staticMethod(); // 这里返回的是Father而不是Son, static语法上重写不会报错,但是从逻辑运行效果上来看达不到多态的目的
son.staticMethod();
}
}
参考链接:https://blog.csdn.net/xjyr/article/details/79435349
好的,正式进入接口与抽象类的讨论了。
首先说说类修饰符:
抽象类就是为了继承而存在的,如果你定义了一个抽象类,却不去继承它,那么等于白白创建了这个抽象类。接口也一样,默认是abstract的,是一个100%的纯抽象类,它就是被大家所实现的。final是最终类修饰符,不可能有子类的。所以抽象类和接口不能被final修饰。因为abstract和final不能同时修饰一个类。
private呢?也不成吧。都是被别人继承的或实现的,设置为private肯定不行的啦。
接口提供两种访问权限:public、default
抽象类的类修饰符为public、protected
为什么抽象类可以有protected而接口不能呢?
答:接口写作interface,是给外界交互用的,写成protected还怎么跟外界交互?抽象类是被继承的,protected对于继承的子类可见。
感觉不是特别好描述,我直接给抽象类和接口来个比较吧。
相同点:它们都不能被实例化。
不同点:
1.接口是抽象类的变体,接口比抽象类更加抽象。抽象类可以提供成员方法的实现细节,而接口中只能存在public abstract 方法
2.抽象类中的成员变量可以是各种类型的,而接口中的成员变量只能是public static final类型的
3.接口中不能含有静态代码块以及静态方法,而抽象类可以有静态代码块和静态方法
对这句做个解释:静态方法不能被子类重写,而接口中的方法都要被实现的,那显然不能存在static方法了。而抽象类写了静态方法,只要别重写它就好了,或者别把它和abstract关键字一起用就好了,只是被继承。因为abstract抽象方法一定要被重写实现的。所以又引申出: abstract方法不能和private、final、static关键字共存 。private私有啊,怎么被重写,访问都访问不到。final,指定该方法不能被重载。
4.一个类只能继承一个抽象类,而一个类却可以实现多个接口
比较了这么多,就是不知道啥时候用抽象类啥时候用接口?从这个方面比较一下这两者的区别我想更好吧。
1.抽象类中不一定都是抽象的方法,也可以有具体实现的方法,这样就可以把大家公用的方法提升到抽象类中,然后具体的方法可以留给子类自己实现(此处经典的应用,模板方法设计模式)。所以抽象类可以更好的实现代码的复用。抽象类作为很多子类的父类,是一种事物的抽象,它是一种模板式设计。而接口是一种行为规范,它是对动作对行为的抽象。
抽象类表示的是,这个对象是什么。接口表示的是,这个对象能做什么。比如,男人,女人,这两个类(如果是类的话……),他们的抽象类是人。说明,他们都是人。人可以吃东西,狗也可以吃东西,你可以把“吃东西”定义成一个接口,然后让这些类去实现它.
所以,在高级语言上,一个类只能继承一个类(抽象类)(正如人不可能同时是生物和非生物),但是可以实现多个接口(吃饭接口、走路接口)。
当你关注一个事物的本质的时候,用抽象类;当你关注一个操作的时候,用接口。
抽象类的功能要远超过接口,但是,定义抽象类的代价高。因为高级语言来说(从实际设计上来说也是)每个类只能继承一个类。在这个类中,你必须继承或编写出其所有子类的所有共性。虽然接口在功能上会弱化许多,但是它只是针对一个动作的描述。而且你可以在一个类中同时实现多个接口。在设计阶段会降低难度的。
来自:https://blog.csdn.net/hanxueyu666/article/details/75712917
2.然后https://www.cnblogs.com/dolphin0520/p/3811437.html这篇文章又从不同的角度比较了抽象类和接口。说是抽象类作为很多子类的父类,它是一种模板式设计。而接口是一种行为规范,它是一种辐射式设计。对于模板式的,只要改动模板就成了,子类不要更改就会自己变化;而对于辐射式,接口改动了实现的子类都得去改变。这个名词用的好!
在工程中常常会说留个接口啊,方便以后拓展。我实现你的接口就可以了。之类的说法。那我程序需要,我就可以实现多个接口啊,做很多种行为。具体例子请看:https://blog.csdn.net/jjjjjj123321/article/details/54135413