上季内容回顾:
1、面向对象中接口与抽象类的具体应用。
可以通过对象的多态性,为父类实例化,之后一切的操作标准以父类为主。
本季主要知识点:
讲解抽象类与接口的关系。
1、一个抽象类中能否包含一个接口呢?
abstract class A
{
public abstract void fun();
interface B
{
public void print();
}
}
我们来验证测试下哈~发现生成A$B.class,表示B作为A的内部接口,证明一个抽象类中可以包含一个内部接口。
那怎么使用呢?我们看下面哈~
首先我们先子类X覆写父类A方法但不覆写接口B中的方法
abstract class A
{
public abstract void fun();
interface B
{
public void print();
}
}
class X extends A
{
//覆写父类fun()方法
public void fun()
{
System.out.println( "Hello World!!!");
}
}
发现编译没有问题哈~
现在我们测试覆写接口方法哈~
abstract class A
{
public abstract void fun();
interface B
{
public void print();
}
}
class X extends A
{
//覆写父类fun()方法
public void fun()
{
B b = new Y();
b.print();
}
class Y implements B
{
//覆写父类接口中的方法print()
public void print()
{
System.out.println( "Hello Java!!!");
}
}
}
现在我们加上主方法进行测试哈~
abstract class A
{
public abstract void fun();
interface B
{
public void print();
}
}
class X extends A
{
//覆写父类fun()方法
public void fun()
{
B b = new Y();
b.print();
}
class Y implements B
{
//覆写父类接口中的方法print()
public void print()
{
System.out.println( "Hello Java!!!");
}
}
}
public class Demo01
{
public static void main(String args[])
{
A a = new X();
a.fun();
}
}
证明一个抽象类中可以包含一个接口,之后在抽象类的子类中可以有选择的是否实现抽象类中的接口。
2、一个接口中能否包含一个抽象类呢?同上,都是可以选择是否实现
interface A
{
public void fun();
abstract class B
{
public abstract void print();
}
}
下面我们写上个子类,检验一下是否可以有选择实现抽象类B
interface A
{
public void fun();
abstract class B
{
public abstract void print();
}
}
class X implements A
{
public void fun()
{
}
}
验证可以哈~
下面覆写抽象类B中print()方法
interface A
{
public void fun();
abstract class B
{
public abstract void print();
}
}
class X implements A
{
public void fun()
{
new Y().print();
}
class Y extends B
{
public void print()
{
System.out.println( "Hello World!!!");
}
}
}
public class Demo02
{
public static void main(String args[])
{
A a = new X();
a.fun();
}
}
3、观察以下的程序,验证输出结果
abstract class A
{
public A()
{
this.print();
}
public abstract void print();
}
class B extends A
{
private int i = 30;
public B( int i)
{
this.i = i;
}
public void print()
{
System.out.println( "i = "+i);
}
}
public class Demo03
{
public static void main(String args[])
{
new B(50);
}
}
输出结果为0哈,这与子类对象实例化过程有关哈
回顾:子类对象的实例化过程
・ 子类对象使用new关键字要调用构造方法
・ 调用构造方法时的顺序:先去调用父类中的构造方法(默认为无参构造),之后再调用子类中的构造方法。
・ 调用构造方法的目的:为其内部的属性初始化
・ 子类中的属性在没有完成父类中的构造方法之前,所有的内容都是默认值,整型是“0” 。
思考:
我们知道一个子类如果实现了一个接口则肯定要覆写接口中的全部抽象方法。那问?是否可以采用一种方式,让子类可以有选择的去覆写自己真正需要的方法。
interface Door
{
//开门
public void openDoor();
//关门
public void closeDoor();
//维修
public void repairDoor();
//拆除
public void removeDoor();
//锁门
public void lockDoor();
}
class D implements Door
{
//子类现在肯定要覆写里面全部的抽象方法
}
矛盾点:
・ 子类不需要覆写全部的方法
・ 如果子类直接实现了接口则肯定要覆写全部的方法
・ 解决:如果中间加入了一个过渡端呢?
接口 --> 过渡端 --> 子类
|- 此过渡端不应该被直接使用。 --> 抽象类
过渡端使用抽象类实现最合适,因为抽象类可以实现一个接口同时可以有一些抽象方法,并且不能直接被new关键字实例化。
interface Door
{
//开门
public void openDoor();
//关门
public void closeDoor();
//维修
public void repairDoor();
//拆除
public void removeDoor();
//锁门
public void lockDoor();
}
abstract class DoorAdapter implements Door
{
//但是以下的方法虽然实现了,可是没有具体的方法体
public void openDoor(){}
public void closeDoor(){}
public void repairDoor(){}
public void removeDoor(){}
public void lockDoor(){}
}
class D extends DoorAdapter
{
//子类现在肯定要覆写里面全部的抽象方法
//只需要打开门
public void openDoor()
{
System.out.println( "开门~~~");
}
}
public class Demo04
{
public static void main(String args[])
{
new D().openDoor();
}
}
此处是有选择的在子类实现了所需要的方法。
这种设计称为Adapter(适配器设计)
4、模拟:
・ 张三 很老实 --> 李四,借10000000元,不还
・ 张三 --> 讨债公司 --> 李四 --> 还钱
张三和讨债公司的目的 --> 还钱。
//主题:讨债
interface Subject
{
//完成具体的操作
public void giveMe();
}
//真正要讨债的人
class RealSubject implements Subject
{
public void giveMe()
{
System.out.println( "还我滴Money");
}
}
//代理人
class ProxySubject implements Subject
{
private Subject sub = null;
public ProxySubject(Subject sub)
{
this.sub = sub;
}
public void before()
{
System.out.println( "需要一些准备~~~");
}
public void after()
{
System.out.println( "销毁一些证据~~~");
}
public void giveMe()
{
//也要实现讨债
this.before();
//代表真正的债主去讨债
this.sub.giveMe();
this.after();
}
}
public class Demo05
{
public static void main(String args[])
{
Subject real = new RealSubject();
//委托代理人完成
Subject proxy = new ProxySubject(real);
proxy.giveMe();
}
}
代理设计:
・ 主要在日志上比较多。
・ 一般开发中我们只关注真实主题,而所有的其他操作,比如说日志等操作用户并不需要知道,所以可以在代理中完成这些其他与具体业务逻辑无直接关系的操作。
接口和抽象类图的表示?
总结
面试中:请你详细的解释一下抽象类和接口的不同
#############################################################
本文出自 “王乾De技术博客” 博客,谢绝转载!