抽象类
当定义一个父类的时候,类中会定义一些方法提供给子类重写,若这些方法父类实现了,就会出现误调用(在子类中并没有重写,创建对象的时候,调用该方法,执行的一定是父类的),希望在父类中定义的方法子类必须重写,给予一定提示,若子类不重写,就会报错,此时可以使用抽象方法。
/*
* 抽象类:
* 抽象类是一个特殊的父类,因为这个类可以存在抽象方法
* 抽象类可以提供抽象方法,也可以不提供抽象方法
* 抽象方法是定义在抽象类中没有方法体的方法,只要是继承于抽象类就必须实现抽象方法
* ps:必须实现不是一定的,抽象类继承于抽象类可以不实现
*
* ps:在开发中父类是不会直接创建对象的,私有化构造方法,为了限制父类直接创建对象,此时父类可以作为抽象类使用
*/
public class Test {
public static void main(String[] args) {
YueBuQun s = new YueBuQun();
s.practice();
//SunflowerBible b1 = new SunflowerBible();抽象类是不能直接创建对象的
//因为抽象类是一个特殊的父类,所有一定存在多态的概念
//间接的创建父类对象
SunflowerBible b = new YueBuQun();
b.practice();
}
}
abstract class SunflowerBible {
//葵花宝典第一页 -->练习
//抽象方法 抽象方法必须存在在抽象类中
public abstract void practice();
}
class YueBuQun extends SunflowerBible{
@Override
public void practice() {
System.out.println("不可描述......");
}
}
1.抽象类是一个特殊的父类,因为抽象类可以提供抽象方法,抽象类不能直接创建对象,但是可以通过多态的形式来构建对象
2.普通类继承于抽象类必须实现抽象类中的抽象方法
3.抽象类继承于抽象类可以实现抽象父类中的抽象方法也可以不实现并且可以提供自己的抽象方法
4.普通类继承于抽象子类,必须实现所有的抽象方法,若抽象子类中已经实现原有抽象父类中抽象方法普通类可以再次重写
ps:抽象类是为了继承而生的,抽象中是必须有构造方法的,子类中的构造方法是可以直接调用super()来完成
接口
- 接口水管问题:
墙上有个圆形的口,但是按照原本的: 三角形水管两端是三角形 正方形水管两端是正方形 椭圆形水管两端是椭圆形 那是肯定接不上的,因为三角形、正方形、椭圆形的口怎么和墙壁上圆形的口对接呢? 所以先要实现接口,把: 三角形水管一端做成圆形 正方形水管一端做成圆形 椭圆形水管一端做成圆形 ,圆形接口做出来了,具体实现是客户去安装,接口本身并不会安装其他形状的水管,换句话说就是接口没有具体实现,只是告诉你,你的水管要接入,必须有一端是圆形的(接口的约束),因为我只留这个圆形的接口,你要装别的形状的管子,先把一端弄成圆形的就好了(子类去实现接口的方法),不管什么形状,都要一个必须做成圆形才能对接得上,它必须要你按照我的规范来做。
这就是为什么新手会觉得接口什么都不做,只定义接口,没有任何实现,那不是多此一举吗?因为它的实现是子类去完成。
这样只要客户喜欢什么形状的水管,只要实现了我的接口(圆形),都能对接得上,而且改变起来也很方便,只要把水管扭上去就行了,不用在去给墙壁挖洞了
- JDK1.7之前:
/*
* 接口:
* 一个特殊的抽象父类,接口可以提供抽象方法,不能提供构造方法,是由子类实现使用的
* 接口是一种规范,制定一些规则,假如完成某件事情,这个事情需要有规范来约束,此时就必须实现这个接口
*/
interface ISunflowerBible {
//JDK1.7之前:
//静态常量 -->默认修饰 public static final
String BOOK_NAME = "葵花宝典";
//抽象方法 --> 默认修饰 public abstract
void practice();
}
class YBQ implements ISunflowerBible{
@Override
public void practice() {
System.out.println("不可描述.....");
}
}
- JDK1.8之后:
/*
* 如何看待default 和 static 方法:
* default就相当于是类中的成员方法
* static就相当于是类中的静态方法
*/
interface InterfaceForJDK {
String INTERFACE_NAME = "JDK1.8";//全局常量
void show();//抽象方法
//可以在接口中实现两类方法 --> 默认权限修饰public
//这两类方法没有个数限制
default void showInfosDefault() {
System.out.println("接口中default方法");
}
static void showInfosStatic() {
System.out.println("接口中static方法");
}
}
class ImplInterface implements InterfaceForJDK{
@Override
public void show() {
System.out.println(InterfaceForJDK.INTERFACE_NAME);
showInfosDefault();
InterfaceForJDK.showInfosStatic();
}
//default修饰的方法可以重写 static修饰的不能重写
@Override
public void showInfosDefault() {}
}
default/static 方法访问权限默认是 public,且只能是 public
- 接口特点:
//A接口
interface InterfaceA {
void show();
}
//B接口
interface InterfaceB {
void display();
}
//接口C
interface InterfaceC extends InterfaceA,InterfaceB{
//接口是支持多继承的,多个接口之间使用,隔开
}
/*
* 1.抽象类实现接口,可以实现抽象方法也可以不实现(抽象方法可以存在在抽象类中)
* 2.抽象类还可以提供自己的抽象方法
*/
//普通类实现接口必须必须实现接口中的所有抽象方法,可以重写接口中提供的default方法
- 总结:
接口和抽象类相同点:
1.无论是接口还是抽象类,都是位于继承成顶端,都是用来被其他类继承或实现的
2.都不能直接创建对象
3.都可以定义抽象方法,并且可以实现方法(抽象类中可以提供成员方法和静态方法)(接口中可以提供 defalut 和 static方法)
不同点:
1.接口没有构造方法,抽象类有构造方法
2.抽象类可以包含成员方法和抽象方法,接口在1.7之前只能有抽象方法,1.8开始可以有default和static方法
3.一个类只能继承一个抽象父类(单继承),一个类可以实现多个接口(多实现)
4.接口中定义的变量默认就是:全局静态常量 public static final,方法默认都是 public 权限修饰,抽象方法可以不写 public abstract
- 接口多态:
/*
* 设计两个接口,空运接口和陆运接口,有三家快递公司:
* 韵达快递:只能陆运
* 申通快递:只能空运
* 顺丰快递:既能陆运,也能空运
* 人需要发送快递,发陆运只能走韵达和顺丰,发空运只能走申通和顺丰
*/
public class Interface {
public static void main(String[] args) {
Person p = new Person("小明");
YunDa yd = new YunDa("韵达快递");
ShenTong st = new ShenTong("申通快递");
ShunFeng sf = new ShunFeng("顺丰快递");
p.sendIAir(st);
p.sendILand(yd);
}
}
class Company{
private String name;
public Company() {
super();
}
public Company(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
class YunDa extends Company implements LandTransport{
public YunDa() {
super();
}
public YunDa(String name) {
super(name);
}
@Override
public void landTransport() {
System.out.println(getName()+"走陆运发快递");
}
}
class ShenTong extends Company implements AirTransport{
public ShenTong() {
super();
}
public ShenTong(String name) {
super(name);
}
@Override
public void airTransport() {
System.out.println(getName()+"走空运发快递");
}
}
class ShunFeng extends Company implements LandTransport,AirTransport{
public ShunFeng() {
super();
}
public ShunFeng(String name) {
super(name);
}
@Override
public void airTransport() {
System.out.println(getName()+"走空运发快递");
}
@Override
public void landTransport() {
System.out.println(getName()+"走陆运发快递");
}
}
class Person {
private String name;
public Person() {
super();
}
public Person(String name) {
super();
this.name = name;
}
//接口多态--> 父类可以接收一个子类的引用
//接口是一个特殊的抽象父类 --> 就可以当做父类来使用
public void sendIAir(AirTransport airTransport) {
System.out.print(name+"通过");
airTransport.airTransport();
}
public void sendILand(LandTransport landTransport) {
System.out.print(name+"通过");
landTransport.landTransport();
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}