java类继承或者实现自己内部的抽象类或者接口是不允许的
https://gcc.gnu.org/legacy-ml/gcc-patches/2001-04/msg01330.html
比如:
class A extend A.B{
static class B{
void fun(){};
}
}
会报错:
Cyclic inheritance involving 'com.xxx.xxx.A'
意思就是循环调用,B的存在需要A的存在(因为B是A的内部类),而A的存在又需要B的存在(因为A继承B),这时编译器就不知道先编译谁了,就好像是让计算机去解决“先有鸡还是先有蛋”的问题,它会很懵逼!
上述这样写的目的:A想复用或者扩展B中的fun函数!
解决方案:
1.内部类改成外部类,使用继承(A可以直接调用B中的fun或者重写fun)
class B{ void fun(){};}
class A extend B{
}
2.使用组合类(A持有B的对象引用,A就可以直接调用B中的fun或者自己扩展)
package com.klx.rvdemo;
public class A{
//
class B{
void fun(){};// B的fun函数
}
//
B b;
public A(B b){// 通过构造函数向A传入B引用
this.b = b;
}
// A自己的fun函数
void fun(){
b.fun();// 调用了B的fun函数
}
}
3.方式2可以发现A,B的fun函数名都一样,可以把相同函数变为接口(接口的所有实现类都必须实现接口里的函数)
package com.klx.rvdemo;
interface I{
void fun();
}
public class A implements I{
//
class B implements I{
@Override
public void fun() {
}
}
//
I i;
public A(I i){
this.i = i;
}
@Override
public void fun() {
i.fun();
}
}
4.发现方式3可以直接把A中内部类B删除了,没有影响(A依赖接口I而不再是依赖B,以后传递给A的就是I的实现类引用)
package com.klx.rvdemo;
interface I{
void fun();
}
public class A implements I{
I i;
public A(I i){
this.i = i;
}
@Override
public void fun() {
i.fun();
}
}
5.当使用方式4的时候,发现给A构造函数传递I的实现类引用的时候可以用lambda表达式,直接传了个函数进去。
package com.klx.rvdemo;
interface I{
void fun();
}
public class A implements I{
I i;
public A(I i){
this.i = i;
}
@Override
public void fun() {
i.fun();
}
// test
public static void main(String[] args) {
I i = new A(() -> {
System.out.println("this is B fun");
});
i.fun();
}
}
上面分析过程可总结为:
1.面向对象编程
2.使用继承
3.使用组合
4.面向接口编程
5.函数式编程
end