从语法的角度上来讲
is-a代表继承,也就是extends,继承完整实现的类或者用abstract修饰的类(子类需要实现abstract修饰的方法)
has-a代表组合,设计模式中多次推崇组合好处大于继承,这里组合就是指成员变量类型是其他类
is-like-a代表的是 拥有、像某个行为,和继承最大的不同,is-like-a仅仅对某一种行为进行继承,java中使用interface
从使用角度来看
public abstract class Person {
public void run() {
hand();
feet();
}
public void toStPrint() {
System.out.println("Person has hand feet");
}
public abstract void hand();
public abstract void feet();
}
``
抽象Person类,要实现的就是一个人来做事情,使用手和脚进行搭配,通过子类的继承实现
多说一点,abstract默认就是public,也只能是public
java的这种把接口和抽象类分开的机制很好,c++中就全靠自觉了,并且c++中virtual是可以有实现的,c++中使用 virtual = 0实现java的abstract
如果使用接口
public interface Persion1 {
public abstract void run();
public abstract void toStPrint();
public abstract void hand();
public abstract void feet();
}
注意的是,接口中的public abstract可以省略,看出区别来没,接口其实就是对抽象的进一步抽象,只不过接口要求更严格,这里讨论静态方法(public static的方法)、默认方法(default的方法)、静态变量(public static修饰的变量)
接口中仅仅定义的函数,子类需要一一进行实现
上面来看很明显是abstract更优,使用abstract作为主导,interface作为附加,abstract是必须有的,比如人的手和脚,但是接口不是必须的比如赚钱的数量。
1.自己实现的类中应该是abstract为主体,interface为附加
2.对于给第三方提供的调用接口那肯定提供的是接口,因为第三方不关心实现,只关心调用
3.套用设计模式的道理,变量的类型不能是具体类,应该是其抽象的父类
4.不应该覆盖父类的方法,如果这样说明你的父类不够抽象,方法不是集中提取的
5.不要让类派生自具体的类,那样会存在依赖关系
6.必要的时候使用依赖倒置,现有很多的人,那么你想人的动作是否可以抽象出一个类进行给外界共同调用?
##从编译器角度看
其实编译器进行的是类型检查,如果是abstract就看abstract修饰的方法是否正确
如果是interface就看interface修饰的方法是否正确,interface是特殊的abstract
##解耦
其实解耦最大的目的,就是让代码之间不需要彼此依赖,一般解耦的基础都是多态,所以我们一旦定义的抽象类中的函数那就是给外界调用的,使用抽象类的引用实现这个类的功能就好了