类的复用两钟常用方式
1:继承,2聚合,组合
组合:同一生命周期的强关联关系,如人和心脏的关系,聚合:全体和单个的关系,可以独立的存在,体现在代码上的区别是组合关系会在类属性定义的时候初始化,或者在构造函数中初始化,而聚合关系在类中保留一个其他类的对象引用,在使用的时候动态传进一个对象,比如用电脑打游戏,可以在电脑上保留一个游戏对象的指针,当打游戏这个动作触发的时候,传进来一个具体的游戏对象。
聚合组合带来的复用是更加符合开闭原则的,但是要设计好每一个单独的模块,或者对象的功能界限,不然可能出现一个类存在很多其他类的对象,或者一个对象提供的功能太多,导致的逻辑越界带来的不好维护。
继承关系:当需要用到多态,向上造型的时候才考虑使用继承,比如工厂模式,抽象工厂等。若需要使用继承,一定要吧这一类的对象的所有共同点抽象出来,否则是毫无意义的。
同时对于那些不可修改的方法是有必要定义为final的。
继承关系带来的类的初始化的顺序:假设 A extends B 当我们使用到A类中的静态方法或者属性时(main方法也是静态的),会去加载B类,初始化B类的staic的属性,代码块。然后初始化B的static的属性,代码块。这个时候若是需要创建一个A类的对象,在new的时候jvm会去分配内存,这个时候会初始化二进制0,然后给B类的属性赋值,基本类型有初始值,对象是NULL,然后调用B的构造函数,然后初始化A的属性(在这之前,基本类型的属性都是0,哪怕你显示的声明int i=10),调用A的构造函数。这里需要注意的是java的动态绑定机制,java类的属性时静态绑定的,不会因为子类定义相同的字段覆盖父类的字段值,但是方法是动态绑定的,是可以被override的。当然这里不包含private的字段和方法,
B b = new A();
这个时候我们拿到b这个引用可以获取到B类的非private的字段,和B类的方法(若有方法的覆盖,只能调用到A类的覆盖后的方法)
A a = (A)b;
这个时候我们就可以用a 这个引用获取到A类对象里面的字段和A的方法(包括从B继承来的)。
但是这样向下造型是有危险的,故最好用instans of 判断一下
final;final的字段是不允许改变的,方法是不允许覆盖的。
使用final字段必须要保证在使用之前初始化,所以可以在声明的时候初始化,或者构造函数里面初始化。所以我们可以利用在构造函数里面初始化创建拥有不同final值的对象,
final字段若是一个引用,则表示这个引用不能指向其他对象,但是对象里面的值是可以改变的
static :必须显示的声明并初始化。
所以在继承和组合中,如果不是用到多态和向上造型,还是不要用继承的好,因为继承会把父类的方法细节暴露出来,若是父类修改了方法,子类也要受到影响。
父类声明了一个STATIC方法,子类也可以声明一个static同样名字的方法。调用的时候,引用是什么类型就是那个类的方法,这样的statIC 方法是属于类的,所以不能称之为继承。final 子类不可以出现一样的。